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.
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
@@ -53,25 +53,6 @@ class PoolAdapter(BaseAdapter):
53
53
  self.logger.error(f"Error fetching pools by IDs: {e}")
54
54
  return (False, str(e))
55
55
 
56
- async def get_all_pools(
57
- self, merge_external: bool | None = None
58
- ) -> tuple[bool, PoolList | str]:
59
- """
60
- Get all available pools.
61
-
62
- Args:
63
- merge_external: Whether to merge external data
64
-
65
- Returns:
66
- Tuple of (success, data) where data is all pools or error message
67
- """
68
- try:
69
- data = await self.pool_client.get_all_pools(merge_external=merge_external)
70
- return (True, data)
71
- except Exception as e:
72
- self.logger.error(f"Error fetching all pools: {e}")
73
- return (False, str(e))
74
-
75
56
  async def get_llama_matches(self) -> tuple[bool, dict[str, LlamaMatch] | str]:
76
57
  """
77
58
  Get Llama protocol matches for pools.
@@ -105,178 +86,3 @@ class PoolAdapter(BaseAdapter):
105
86
  except Exception as e:
106
87
  self.logger.error(f"Error fetching Llama reports: {e}")
107
88
  return (False, str(e))
108
-
109
- async def find_high_yield_pools(
110
- self,
111
- min_apy: float = 0.01,
112
- min_tvl: float = 1000000,
113
- stablecoin_only: bool = True,
114
- network_codes: list[str] | None = None,
115
- ) -> tuple[bool, Any]:
116
- """
117
- Find high-yield pools based on criteria.
118
-
119
- Args:
120
- min_apy: Minimum APY threshold (as decimal, e.g., 0.01 for 1%)
121
- min_tvl: Minimum TVL threshold in USD
122
- stablecoin_only: Whether to filter for stablecoin pools only
123
- network_codes: List of network codes to filter by
124
-
125
- Returns:
126
- Tuple of (success, data) where data is filtered pools or error message
127
- """
128
- try:
129
- # Get Llama matches for yield data
130
- success, llama_data = await self.get_llama_matches()
131
- if not success:
132
- return (False, f"Failed to fetch Llama data: {llama_data}")
133
-
134
- matches = llama_data.get("matches", [])
135
- filtered_pools = []
136
-
137
- for pool in matches:
138
- # Apply filters
139
- if stablecoin_only and not pool.get("llama_stablecoin", False):
140
- continue
141
-
142
- if pool.get("llama_tvl_usd", 0) < min_tvl:
143
- continue
144
-
145
- if (
146
- pool.get("llama_apy_pct", 0) < min_apy * 100
147
- ): # Convert to percentage
148
- continue
149
-
150
- if network_codes and pool.get("network", "").lower() not in [
151
- nc.lower() for nc in network_codes
152
- ]:
153
- continue
154
-
155
- filtered_pools.append(pool)
156
-
157
- # Sort by APY descending
158
- filtered_pools.sort(key=lambda x: x.get("llama_apy_pct", 0), reverse=True)
159
-
160
- return (
161
- True,
162
- {
163
- "pools": filtered_pools,
164
- "total_found": len(filtered_pools),
165
- "filters_applied": {
166
- "min_apy": min_apy,
167
- "min_tvl": min_tvl,
168
- "stablecoin_only": stablecoin_only,
169
- "network_codes": network_codes,
170
- },
171
- },
172
- )
173
- except Exception as e:
174
- self.logger.error(f"Error finding high yield pools: {e}")
175
- return (False, str(e))
176
-
177
- async def get_pool_analytics(self, pool_ids: list[str]) -> tuple[bool, Any]:
178
- """
179
- Get comprehensive analytics for specific pools.
180
-
181
- Args:
182
- pool_ids: List of pool identifiers
183
-
184
- Returns:
185
- Tuple of (success, data) where data is pool analytics or error message
186
- """
187
- try:
188
- # Get pool data
189
- success, pool_data = await self.get_pools_by_ids(pool_ids)
190
- if not success:
191
- return (False, f"Failed to fetch pool data: {pool_data}")
192
-
193
- # Get Llama reports
194
- success, llama_data = await self.get_llama_reports(pool_ids)
195
- if not success:
196
- self.logger.warning(f"Failed to fetch Llama data: {llama_data}")
197
- llama_data = {}
198
-
199
- pools = pool_data.get("pools", [])
200
- llama_reports = llama_data
201
-
202
- # Combine data
203
- analytics = []
204
- for pool in pools:
205
- pool_id = pool.get("id")
206
- llama_report = llama_reports.get(pool_id.lower()) if pool_id else None
207
-
208
- analytics.append(
209
- {
210
- "pool": pool,
211
- "llama_data": llama_report,
212
- "combined_apy": (
213
- llama_report.get("llama_combined_apy_pct", 0) / 100
214
- if llama_report
215
- and llama_report.get("llama_combined_apy_pct") is not None
216
- else pool.get("apy", 0)
217
- ),
218
- "tvl_usd": (
219
- llama_report.get("llama_tvl_usd", 0)
220
- if llama_report and llama_report.get("llama_tvl_usd")
221
- else pool.get("tvl", 0)
222
- ),
223
- }
224
- )
225
-
226
- return (True, {"analytics": analytics, "total_pools": len(analytics)})
227
- except Exception as e:
228
- self.logger.error(f"Error getting pool analytics: {e}")
229
- return (False, str(e))
230
-
231
- async def search_pools(self, query: str, limit: int = 10) -> tuple[bool, Any]:
232
- """
233
- Search pools by name, symbol, or other criteria.
234
-
235
- Args:
236
- query: Search query string
237
- limit: Maximum number of results
238
-
239
- Returns:
240
- Tuple of (success, data) where data is search results or error message
241
- """
242
- try:
243
- success, all_pools_data = await self.get_all_pools()
244
- if not success:
245
- return (False, f"Failed to fetch pools: {all_pools_data}")
246
-
247
- pools = all_pools_data.get("pools", [])
248
- query_lower = query.lower()
249
-
250
- # Simple text search
251
- matching_pools = []
252
- for pool in pools:
253
- name = pool.get("name", "").lower()
254
- symbol = pool.get("symbol", "").lower()
255
- description = pool.get("description", "").lower()
256
-
257
- if (
258
- query_lower in name
259
- or query_lower in symbol
260
- or query_lower in description
261
- ):
262
- matching_pools.append(pool)
263
-
264
- # Sort by relevance (exact matches first)
265
- matching_pools.sort(
266
- key=lambda x: (
267
- query_lower not in x.get("name", "").lower(),
268
- query_lower not in x.get("symbol", "").lower(),
269
- )
270
- )
271
-
272
- return (
273
- True,
274
- {
275
- "pools": matching_pools[:limit],
276
- "total_found": len(matching_pools),
277
- "query": query,
278
- },
279
- )
280
- except Exception as e:
281
- self.logger.error(f"Error searching pools: {e}")
282
- return (False, str(e))
@@ -21,27 +21,6 @@
21
21
  }
22
22
  }
23
23
  },
24
- "get_all_pools": {
25
- "description": "Get all available pools",
26
- "input": {
27
- "merge_external": false
28
- },
29
- "output": {
30
- "success": true,
31
- "data": {
32
- "pools": [
33
- {
34
- "id": "pool-123",
35
- "name": "USDC/USDT Pool",
36
- "symbol": "USDC-USDT",
37
- "apy": 0.05,
38
- "tvl": 1000000
39
- }
40
- ],
41
- "total": 1
42
- }
43
- }
44
- },
45
24
  "get_llama_matches": {
46
25
  "description": "Get Llama protocol matches for pools",
47
26
  "input": {},
@@ -60,84 +39,5 @@
60
39
  ]
61
40
  }
62
41
  }
63
- },
64
- "find_high_yield_pools": {
65
- "description": "Find high-yield pools based on criteria",
66
- "input": {
67
- "min_apy": 0.03,
68
- "min_tvl": 500000,
69
- "stablecoin_only": true,
70
- "network_codes": ["base", "ethereum"]
71
- },
72
- "output": {
73
- "success": true,
74
- "data": {
75
- "pools": [
76
- {
77
- "id": "pool-123",
78
- "llama_apy_pct": 5.2,
79
- "llama_tvl_usd": 1000000,
80
- "llama_stablecoin": true,
81
- "network": "base"
82
- }
83
- ],
84
- "total_found": 1,
85
- "filters_applied": {
86
- "min_apy": 0.03,
87
- "min_tvl": 500000,
88
- "stablecoin_only": true,
89
- "network_codes": ["base", "ethereum"]
90
- }
91
- }
92
- }
93
- },
94
- "get_pool_analytics": {
95
- "description": "Get comprehensive analytics for specific pools",
96
- "input": {
97
- "pool_ids": ["pool-123"]
98
- },
99
- "output": {
100
- "success": true,
101
- "data": {
102
- "analytics": [
103
- {
104
- "pool": {
105
- "id": "pool-123",
106
- "name": "USDC/USDT Pool",
107
- "symbol": "USDC-USDT"
108
- },
109
- "llama_data": {
110
- "llama_apy_pct": 5.2,
111
- "llama_tvl_usd": 1000000
112
- },
113
- "combined_apy": 0.052,
114
- "tvl_usd": 1000000
115
- }
116
- ],
117
- "total_pools": 1
118
- }
119
- }
120
- },
121
- "search_pools": {
122
- "description": "Search pools by name, symbol, or other criteria",
123
- "input": {
124
- "query": "USDC",
125
- "limit": 5
126
- },
127
- "output": {
128
- "success": true,
129
- "data": {
130
- "pools": [
131
- {
132
- "id": "pool-123",
133
- "name": "USDC/USDT Pool",
134
- "symbol": "USDC-USDT",
135
- "description": "Stablecoin pool on Base"
136
- }
137
- ],
138
- "total_found": 1,
139
- "query": "USDC"
140
- }
141
- }
142
42
  }
143
43
  }
@@ -47,25 +47,6 @@ class TestPoolAdapter:
47
47
  pool_ids="pool-123,pool-456", merge_external=True
48
48
  )
49
49
 
50
- @pytest.mark.asyncio
51
- async def test_get_all_pools_success(self, adapter, mock_pool_client):
52
- """Test successful retrieval of all pools"""
53
- # Mock response
54
- mock_response = {
55
- "pools": [
56
- {"id": "pool-123", "name": "Pool 1"},
57
- {"id": "pool-456", "name": "Pool 2"},
58
- ],
59
- "total": 2,
60
- }
61
- mock_pool_client.get_all_pools = AsyncMock(return_value=mock_response)
62
-
63
- success, data = await adapter.get_all_pools(merge_external=False)
64
-
65
- assert success is True
66
- assert data == mock_response
67
- mock_pool_client.get_all_pools.assert_called_once_with(merge_external=False)
68
-
69
50
  @pytest.mark.asyncio
70
51
  async def test_get_llama_matches_success(self, adapter, mock_pool_client):
71
52
  """Test successful Llama matches retrieval"""
@@ -88,106 +69,6 @@ class TestPoolAdapter:
88
69
  assert success is True
89
70
  assert data == mock_response
90
71
 
91
- @pytest.mark.asyncio
92
- async def test_find_high_yield_pools_success(self, adapter, mock_pool_client):
93
- """Test successful high yield pool discovery"""
94
- mock_llama_response = {
95
- "matches": [
96
- {
97
- "pool_id": "pool-123",
98
- "llama_apy_pct": 5.2,
99
- "llama_tvl_usd": 1000000,
100
- "llama_stablecoin": True,
101
- "network": "base",
102
- },
103
- {
104
- "pool_id": "pool-456",
105
- "llama_apy_pct": 2.0,
106
- "llama_tvl_usd": 500000,
107
- "llama_stablecoin": True,
108
- "network": "ethereum",
109
- },
110
- {
111
- "pool_id": "pool-789",
112
- "llama_apy_pct": 6.0,
113
- "llama_tvl_usd": 2000000,
114
- "llama_stablecoin": False,
115
- "network": "base",
116
- },
117
- ]
118
- }
119
- mock_pool_client.get_llama_matches = AsyncMock(return_value=mock_llama_response)
120
-
121
- success, data = await adapter.find_high_yield_pools(
122
- min_apy=0.03, min_tvl=500000, stablecoin_only=True, network_codes=["base"]
123
- )
124
-
125
- assert success is True
126
- assert len(data["pools"]) == 1 # Only pool-123 meets criteria
127
- assert (
128
- data["pools"][0].get("pool_id") == "pool-123"
129
- or data["pools"][0].get("id") == "pool-123"
130
- )
131
- assert data["total_found"] == 1
132
- assert data["filters_applied"]["min_apy"] == 0.03
133
- assert data["filters_applied"]["stablecoin_only"] is True
134
-
135
- @pytest.mark.asyncio
136
- async def test_get_pool_analytics_success(self, adapter, mock_pool_client):
137
- """Test successful pool analytics generation"""
138
- mock_pool_data = {
139
- "pools": [
140
- {"id": "pool-123", "name": "USDC/USDT Pool", "symbol": "USDC-USDT"}
141
- ]
142
- }
143
- mock_pool_client.get_pools_by_ids = AsyncMock(return_value=mock_pool_data)
144
-
145
- mock_llama_data = {
146
- "pool-123": {
147
- "llama_apy_pct": 5.2,
148
- "llama_combined_apy_pct": 5.2,
149
- "llama_tvl_usd": 1000000,
150
- }
151
- }
152
- mock_pool_client.get_llama_reports = AsyncMock(return_value=mock_llama_data)
153
-
154
- success, data = await adapter.get_pool_analytics(["pool-123"])
155
-
156
- assert success is True
157
- assert len(data["analytics"]) == 1
158
- assert data["analytics"][0]["pool"]["id"] == "pool-123"
159
- assert round(data["analytics"][0]["combined_apy"], 6) == round(0.052, 6)
160
- assert data["analytics"][0]["tvl_usd"] == 1000000
161
-
162
- @pytest.mark.asyncio
163
- async def test_search_pools_success(self, adapter, mock_pool_client):
164
- """Test successful pool search"""
165
- mock_all_pools = {
166
- "pools": [
167
- {
168
- "id": "pool-123",
169
- "name": "USDC/USDT Pool",
170
- "symbol": "USDC-USDT",
171
- "description": "Stablecoin pool on Base",
172
- },
173
- {
174
- "id": "pool-456",
175
- "name": "ETH/WETH Pool",
176
- "symbol": "ETH-WETH",
177
- "description": "Ethereum pool",
178
- },
179
- ]
180
- }
181
- mock_pool_client.get_all_pools = AsyncMock(return_value=mock_all_pools)
182
-
183
- success, data = await adapter.search_pools("USDC", limit=5)
184
-
185
- assert success is True
186
- assert len(data["pools"]) == 1
187
- assert data["pools"][0]["id"] == "pool-123"
188
- assert data["total_found"] == 1
189
- assert data["query"] == "USDC"
190
-
191
72
  @pytest.mark.asyncio
192
73
  async def test_get_pools_by_ids_failure(self, adapter, mock_pool_client):
193
74
  """Test pool retrieval failure"""
@@ -200,21 +81,6 @@ class TestPoolAdapter:
200
81
  assert success is False
201
82
  assert "API Error" in data
202
83
 
203
- @pytest.mark.asyncio
204
- async def test_find_high_yield_pools_no_matches(self, adapter, mock_pool_client):
205
- """Test high yield pool discovery with no matches"""
206
- mock_llama_response = {"matches": []}
207
- mock_pool_client.get_llama_matches.return_value = mock_llama_response
208
-
209
- success, data = await adapter.find_high_yield_pools(
210
- min_apy=0.10,
211
- min_tvl=10000000,
212
- )
213
-
214
- assert success is True
215
- assert len(data["pools"]) == 0
216
- assert data["total_found"] == 0
217
-
218
84
  def test_adapter_type(self, adapter):
219
85
  """Test adapter has adapter_type"""
220
86
  assert adapter.adapter_type == "POOL"
@@ -12,7 +12,7 @@ The adapter uses the TokenClient which automatically handles authentication and
12
12
 
13
13
  The TokenClient will automatically:
14
14
  - Use the WAYFINDER_API_URL from settings
15
- - Handle authentication via environment variables or config.json
15
+ - Handle authentication via config.json
16
16
  - Manage token refresh and retry logic
17
17
 
18
18
  ## Usage
@@ -1,4 +1,3 @@
1
- import os
2
1
  from typing import Any
3
2
 
4
3
  from loguru import logger
@@ -30,8 +29,6 @@ class AuthClient(WayfinderClient):
30
29
  creds = self._load_config_credentials()
31
30
  if creds.get("api_key"):
32
31
  return True
33
- if os.getenv("WAYFINDER_API_KEY"):
34
- return True
35
32
  except Exception:
36
33
  pass
37
34
 
@@ -27,6 +27,7 @@ class BRAPQuote(TypedDict):
27
27
  amount1: Required[str]
28
28
  amount2: NotRequired[str]
29
29
  routes: NotRequired[list[dict[str, Any]]]
30
+ best_route: NotRequired[dict[str, Any]]
30
31
  fees: NotRequired[dict[str, Any] | None]
31
32
  slippage: NotRequired[float | None]
32
33
  wayfinder_fee: NotRequired[float | None]
@@ -15,14 +15,10 @@ from wayfinder_paths.core.clients.protocols import (
15
15
  HyperlendClientProtocol,
16
16
  LedgerClientProtocol,
17
17
  PoolClientProtocol,
18
- SimulationClientProtocol,
19
18
  TokenClientProtocol,
20
- TransactionClientProtocol,
21
19
  WalletClientProtocol,
22
20
  )
23
- from wayfinder_paths.core.clients.SimulationClient import SimulationClient
24
21
  from wayfinder_paths.core.clients.TokenClient import TokenClient
25
- from wayfinder_paths.core.clients.TransactionClient import TransactionClient
26
22
  from wayfinder_paths.core.clients.WalletClient import WalletClient
27
23
 
28
24
 
@@ -32,7 +28,7 @@ class ClientManager:
32
28
 
33
29
  Args:
34
30
  clients: Optional dict of pre-instantiated clients to inject directly.
35
- Keys: 'token', 'hyperlend', 'ledger', 'wallet', 'transaction', 'pool', 'brap', 'simulation'.
31
+ Keys: 'token', 'hyperlend', 'ledger', 'wallet', 'transaction', 'pool', 'brap'.
36
32
  If not provided, defaults to HTTP-based clients.
37
33
  skip_auth: If True, skips authentication (for SDK usage).
38
34
  """
@@ -59,12 +55,10 @@ class ClientManager:
59
55
  self._auth_client: AuthClient | None = None
60
56
  self._token_client: TokenClientProtocol | None = None
61
57
  self._wallet_client: WalletClientProtocol | None = None
62
- self._transaction_client: TransactionClientProtocol | None = None
63
58
  self._ledger_client: LedgerClientProtocol | None = None
64
59
  self._pool_client: PoolClientProtocol | None = None
65
60
  self._hyperlend_client: HyperlendClientProtocol | None = None
66
61
  self._brap_client: BRAPClientProtocol | None = None
67
- self._simulation_client: SimulationClientProtocol | None = None
68
62
 
69
63
  def _get_or_create_client(
70
64
  self,
@@ -109,13 +103,6 @@ class ClientManager:
109
103
  """Get or create token client"""
110
104
  return self._get_or_create_client("_token_client", "token", TokenClient)
111
105
 
112
- @property
113
- def transaction(self) -> TransactionClientProtocol:
114
- """Get or create transaction client"""
115
- return self._get_or_create_client(
116
- "_transaction_client", "transaction", TransactionClient
117
- )
118
-
119
106
  @property
120
107
  def ledger(self) -> LedgerClientProtocol:
121
108
  """Get or create ledger client"""
@@ -143,13 +130,6 @@ class ClientManager:
143
130
  """Get or create BRAP client"""
144
131
  return self._get_or_create_client("_brap_client", "brap", BRAPClient)
145
132
 
146
- @property
147
- def simulation(self) -> SimulationClientProtocol:
148
- """Get or create simulation client"""
149
- return self._get_or_create_client(
150
- "_simulation_client", "simulation", SimulationClient
151
- )
152
-
153
133
  async def authenticate(
154
134
  self,
155
135
  username: str | None = None,
@@ -206,5 +186,4 @@ class ClientManager:
206
186
  "wallet": self._wallet_client,
207
187
  "hyperlend": self._hyperlend_client,
208
188
  "brap": self._brap_client,
209
- "simulation": self._simulation_client,
210
189
  }
@@ -85,22 +85,6 @@ class PoolClient(WayfinderClient):
85
85
  data = response.json()
86
86
  return data.get("data", data)
87
87
 
88
- async def get_all_pools(self, *, merge_external: bool | None = None) -> PoolList:
89
- """
90
- Fetch all pools.
91
-
92
- Example:
93
- GET /api/v1/public/pools/?merge_external=false
94
- """
95
- url = f"{self.api_base_url}/public/pools/"
96
- params: dict[str, Any] = {}
97
- if merge_external is not None:
98
- params["merge_external"] = "true" if merge_external else "false"
99
- response = await self._request("GET", url, params=params, headers={})
100
- response.raise_for_status()
101
- data = response.json()
102
- return data.get("data", data)
103
-
104
88
  async def get_llama_matches(self) -> dict[str, LlamaMatch]:
105
89
  """
106
90
  Fetch Llama matches for pools.
@@ -33,14 +33,6 @@ class PoolBalance(TypedDict):
33
33
  usd_value: NotRequired[float | None]
34
34
 
35
35
 
36
- class EnrichedBalances(TypedDict):
37
- """Enriched token balances response structure"""
38
-
39
- wallet_address: Required[str]
40
- balances: Required[list[TokenBalance]]
41
- total_usd_value: NotRequired[float | None]
42
-
43
-
44
36
  class WalletClient(WayfinderClient):
45
37
  def __init__(self, api_key: str | None = None):
46
38
  super().__init__(api_key=api_key)
@@ -121,17 +121,17 @@ class WayfinderClient:
121
121
 
122
122
  async def _ensure_bearer_token(self) -> bool:
123
123
  """
124
- Ensure Authorization header is set. Priority: existing header > constructor api_key > config.json api_key > env api_key > config.json tokens > env tokens > username/password.
124
+ Ensure Authorization header is set. Priority: existing header > constructor api_key > config.json api_key > config.json tokens > username/password.
125
125
  Raises PermissionError if no credentials found.
126
126
  """
127
127
  if self.headers.get("Authorization"):
128
128
  return True
129
129
 
130
- # Check for API key: constructor > config.json > environment
130
+ # Check for API key: constructor > config.json
131
131
  api_key = self._api_key
132
132
  if not api_key:
133
133
  creds = self._load_config_credentials()
134
- api_key = creds.get("api_key") or os.getenv("WAYFINDER_API_KEY")
134
+ api_key = creds.get("api_key")
135
135
 
136
136
  if api_key:
137
137
  api_key = api_key.strip() if isinstance(api_key, str) else api_key
@@ -142,12 +142,7 @@ class WayfinderClient:
142
142
 
143
143
  # Fall back to OAuth token-based auth
144
144
  creds = self._load_config_credentials()
145
- access = os.getenv("WAYFINDER_ACCESS_TOKEN")
146
- refresh = creds.get("refresh_token") or os.getenv("WAYFINDER_REFRESH_TOKEN")
147
-
148
- if access:
149
- self.set_tokens(access, refresh)
150
- return True
145
+ refresh = creds.get("refresh_token")
151
146
 
152
147
  if refresh:
153
148
  self._refresh_token = refresh
@@ -155,8 +150,8 @@ class WayfinderClient:
155
150
  if refreshed:
156
151
  return True
157
152
 
158
- username = creds.get("username") or os.getenv("WAYFINDER_USERNAME")
159
- password = creds.get("password") or os.getenv("WAYFINDER_PASSWORD")
153
+ username = creds.get("username")
154
+ password = creds.get("password")
160
155
 
161
156
  if username and password:
162
157
  try:
@@ -178,7 +173,7 @@ class WayfinderClient:
178
173
  pass
179
174
 
180
175
  raise PermissionError(
181
- "Not authenticated: provide api_key (via constructor, config.json, or WAYFINDER_API_KEY env var) for service account auth, "
176
+ "Not authenticated: provide api_key (via constructor or config.json) for service account auth, "
182
177
  "or username+password/refresh_token in config.json for personal access"
183
178
  )
184
179
 
@@ -201,11 +196,11 @@ class WayfinderClient:
201
196
  # Ensure API key or bearer token is set in headers if available and not already set
202
197
  # This ensures API keys are passed to all endpoints (including public ones) for rate limiting
203
198
  if not self.headers.get("Authorization"):
204
- # Try to get API key from constructor, config, or env
199
+ # Try to get API key from constructor or config
205
200
  api_key = self._api_key
206
201
  if not api_key:
207
202
  creds = self._load_config_credentials()
208
- api_key = creds.get("api_key") or os.getenv("WAYFINDER_API_KEY")
203
+ api_key = creds.get("api_key")
209
204
 
210
205
  if api_key:
211
206
  api_key = api_key.strip() if isinstance(api_key, str) else api_key