wayfinder-paths 0.1.13__py3-none-any.whl → 0.1.15__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 (61) hide show
  1. wayfinder_paths/adapters/balance_adapter/README.md +13 -14
  2. wayfinder_paths/adapters/balance_adapter/adapter.py +73 -32
  3. wayfinder_paths/adapters/balance_adapter/test_adapter.py +123 -0
  4. wayfinder_paths/adapters/brap_adapter/README.md +11 -16
  5. wayfinder_paths/adapters/brap_adapter/adapter.py +144 -78
  6. wayfinder_paths/adapters/brap_adapter/examples.json +63 -52
  7. wayfinder_paths/adapters/brap_adapter/test_adapter.py +127 -65
  8. wayfinder_paths/adapters/hyperlend_adapter/adapter.py +30 -14
  9. wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +121 -67
  10. wayfinder_paths/adapters/hyperliquid_adapter/test_adapter.py +6 -6
  11. wayfinder_paths/adapters/hyperliquid_adapter/test_adapter_live.py +12 -12
  12. wayfinder_paths/adapters/ledger_adapter/test_adapter.py +6 -6
  13. wayfinder_paths/adapters/moonwell_adapter/adapter.py +332 -9
  14. wayfinder_paths/adapters/moonwell_adapter/test_adapter.py +13 -13
  15. wayfinder_paths/adapters/pool_adapter/README.md +9 -10
  16. wayfinder_paths/adapters/pool_adapter/adapter.py +9 -10
  17. wayfinder_paths/adapters/pool_adapter/test_adapter.py +2 -2
  18. wayfinder_paths/adapters/token_adapter/README.md +2 -14
  19. wayfinder_paths/adapters/token_adapter/adapter.py +16 -10
  20. wayfinder_paths/adapters/token_adapter/examples.json +4 -8
  21. wayfinder_paths/adapters/token_adapter/test_adapter.py +9 -7
  22. wayfinder_paths/core/clients/BRAPClient.py +102 -61
  23. wayfinder_paths/core/clients/ClientManager.py +1 -68
  24. wayfinder_paths/core/clients/HyperlendClient.py +125 -64
  25. wayfinder_paths/core/clients/LedgerClient.py +1 -4
  26. wayfinder_paths/core/clients/PoolClient.py +122 -48
  27. wayfinder_paths/core/clients/TokenClient.py +91 -36
  28. wayfinder_paths/core/clients/WalletClient.py +26 -56
  29. wayfinder_paths/core/clients/WayfinderClient.py +28 -160
  30. wayfinder_paths/core/clients/__init__.py +0 -2
  31. wayfinder_paths/core/clients/protocols.py +35 -46
  32. wayfinder_paths/core/clients/sdk_example.py +37 -22
  33. wayfinder_paths/core/constants/erc20_abi.py +0 -11
  34. wayfinder_paths/core/engine/StrategyJob.py +10 -56
  35. wayfinder_paths/core/services/base.py +1 -0
  36. wayfinder_paths/core/services/local_evm_txn.py +25 -9
  37. wayfinder_paths/core/services/local_token_txn.py +2 -6
  38. wayfinder_paths/core/services/test_local_evm_txn.py +145 -0
  39. wayfinder_paths/core/strategies/Strategy.py +16 -4
  40. wayfinder_paths/core/utils/evm_helpers.py +2 -9
  41. wayfinder_paths/policies/erc20.py +1 -1
  42. wayfinder_paths/run_strategy.py +13 -19
  43. wayfinder_paths/strategies/basis_trading_strategy/strategy.py +77 -11
  44. wayfinder_paths/strategies/basis_trading_strategy/test_strategy.py +6 -6
  45. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +107 -23
  46. wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +54 -9
  47. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/README.md +6 -5
  48. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +2246 -1279
  49. wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +276 -109
  50. wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +1 -1
  51. wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +153 -56
  52. wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +16 -12
  53. wayfinder_paths/templates/adapter/README.md +1 -1
  54. wayfinder_paths/templates/strategy/README.md +3 -3
  55. wayfinder_paths/templates/strategy/test_strategy.py +3 -2
  56. {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.15.dist-info}/METADATA +14 -49
  57. {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.15.dist-info}/RECORD +59 -60
  58. wayfinder_paths/abis/generic/erc20.json +0 -383
  59. wayfinder_paths/core/clients/AuthClient.py +0 -83
  60. {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.15.dist-info}/LICENSE +0 -0
  61. {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.15.dist-info}/WHEEL +0 -0
@@ -24,7 +24,9 @@ class TokenAdapter(BaseAdapter):
24
24
  super().__init__("token_adapter", config)
25
25
  self.token_client = token_client or TokenClient()
26
26
 
27
- async def get_token(self, query: str) -> tuple[bool, TokenDetails | str]:
27
+ async def get_token(
28
+ self, query: str, *, chain_id: int | None = None
29
+ ) -> tuple[bool, TokenDetails | str]:
28
30
  """
29
31
  Get token data by address using the token-details endpoint.
30
32
 
@@ -35,7 +37,7 @@ class TokenAdapter(BaseAdapter):
35
37
  Tuple of (success, data) where data is the token information or error message
36
38
  """
37
39
  try:
38
- data = await self.token_client.get_token_details(query)
40
+ data = await self.token_client.get_token_details(query, chain_id=chain_id)
39
41
  if not data:
40
42
  return (False, f"No token found for: {query}")
41
43
  return (True, data)
@@ -43,7 +45,9 @@ class TokenAdapter(BaseAdapter):
43
45
  self.logger.error(f"Error getting token by query {query}: {e}")
44
46
  return (False, str(e))
45
47
 
46
- async def get_token_price(self, token_id: str) -> tuple[bool, dict[str, Any] | str]:
48
+ async def get_token_price(
49
+ self, token_id: str, *, chain_id: int | None = None
50
+ ) -> tuple[bool, dict[str, Any] | str]:
47
51
  """
48
52
  Get token price by token ID or address using the token-details endpoint.
49
53
 
@@ -54,19 +58,21 @@ class TokenAdapter(BaseAdapter):
54
58
  Tuple of (success, data) where data is the price information or error message
55
59
  """
56
60
  try:
57
- data = await self.token_client.get_token_details(token_id)
61
+ data = await self.token_client.get_token_details(
62
+ token_id, market_data=True, chain_id=chain_id
63
+ )
58
64
  if not data:
59
65
  return (False, f"No token found for: {token_id}")
60
66
 
61
- # Extract just the price information
67
+ price_change_24h = data.get("price_change_24h", 0.0)
62
68
  price_data = {
63
69
  "current_price": data.get("current_price", 0.0),
64
- "price_change_24h": data.get("price_change_24h", 0.0),
65
- "price_change_percentage_24h": data.get(
66
- "price_change_percentage_24h", 0.0
67
- ),
70
+ "price_change_24h": price_change_24h,
71
+ "price_change_percentage_24h": data.get("price_change_percentage_24h")
72
+ if data.get("price_change_percentage_24h") is not None
73
+ else (float(price_change_24h) * 100.0 if price_change_24h else 0.0),
68
74
  "market_cap": data.get("market_cap", 0),
69
- "total_volume": data.get("total_volume", 0),
75
+ "total_volume": data.get("total_volume_usd_24h", 0),
70
76
  "symbol": data.get("symbol", ""),
71
77
  "name": data.get("name", ""),
72
78
  "address": data.get("address", ""),
@@ -1,19 +1,15 @@
1
1
  {
2
2
  "basic_usage": {
3
3
  "description": "Basic usage of TokenAdapter to get token information",
4
- "code": "from adapters.token_adapter.adapter import TokenAdapter\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# Get token by address\nsuccess, data = await adapter.get_token_by_address(\"0x1234567890abcdef1234567890abcdef12345678\")\nif success:\n print(f\"Token symbol: {data.get('symbol')}\")\n print(f\"Token name: {data.get('name')}\")\n print(f\"Decimals: {data.get('decimals')}\")\nelse:\n print(f\"Error: {data}\")"
4
+ "code": "from adapters.token_adapter.adapter import TokenAdapter\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# Get token by address (provide chain_id when querying by address)\nsuccess, data = await adapter.get_token(\n \"0x1234567890abcdef1234567890abcdef12345678\",\n chain_id=8453,\n)\nif success:\n print(f\"Token symbol: {data.get('symbol')}\")\n print(f\"Token name: {data.get('name')}\")\n print(f\"Decimals: {data.get('decimals')}\")\nelse:\n print(f\"Error: {data}\")"
5
5
  },
6
6
  "get_by_token_id": {
7
7
  "description": "Get token information using token ID",
8
- "code": "from adapters.token_adapter.adapter import TokenAdapter\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# Get token by ID\nsuccess, data = await adapter.get_token_by_id(\"token-12345\")\nif success:\n print(f\"Token data: {data}\")\nelse:\n print(f\"Error: {data}\")"
9
- },
10
- "flexible_lookup": {
11
- "description": "Use flexible get_token method that tries both address and token_id",
12
- "code": "from adapters.token_adapter.adapter import TokenAdapter\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# Try both address and token_id\nsuccess, data = await adapter.get_token(\n address=\"0x1234567890abcdef1234567890abcdef12345678\",\n token_id=\"token-12345\"\n)\nif success:\n print(f\"Found token: {data}\")\nelse:\n print(f\"Token not found: {data}\")"
8
+ "code": "from adapters.token_adapter.adapter import TokenAdapter\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# Get token by ID\nsuccess, data = await adapter.get_token(\"token-12345\")\nif success:\n print(f\"Token data: {data}\")\nelse:\n print(f\"Error: {data}\")"
13
9
  },
14
10
  "error_handling": {
15
11
  "description": "Proper error handling for various scenarios",
16
- "code": "from adapters.token_adapter.adapter import TokenAdapter\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# Handle missing parameters\ntry:\n success, data = await adapter.get_token()\n if not success:\n print(f\"Error: {data}\")\nexcept Exception as e:\n print(f\"Unexpected error: {e}\")\n\n# Handle API errors\nsuccess, data = await adapter.get_token_by_address(\"invalid-address\")\nif not success:\n print(f\"API error: {data}\")\nelse:\n print(f\"Token found: {data}\")"
12
+ "code": "from adapters.token_adapter.adapter import TokenAdapter\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# Handle API errors\nsuccess, data = await adapter.get_token(\"invalid-address\")\nif not success:\n print(f\"API error: {data}\")\nelse:\n print(f\"Token found: {data}\")"
17
13
  },
18
14
  "health_check": {
19
15
  "description": "Check adapter health and connectivity",
@@ -21,6 +17,6 @@
21
17
  },
22
18
  "batch_operations": {
23
19
  "description": "Perform multiple token lookups efficiently",
24
- "code": "from adapters.token_adapter.adapter import TokenAdapter\nimport asyncio\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# List of token addresses to lookup\ntoken_addresses = [\n \"0x1234567890abcdef1234567890abcdef12345678\",\n \"0xabcdef1234567890abcdef1234567890abcdef12\",\n \"0x9876543210fedcba9876543210fedcba98765432\"\n]\n\n# Batch lookup\ntoken_data = {}\nfor address in token_addresses:\n success, data = await adapter.get_token_by_address(address)\n if success:\n token_data[address] = data\n else:\n print(f\"Failed to get token for {address}: {data}\")\n\nprint(f\"Successfully retrieved {len(token_data)} tokens\")\nfor address, data in token_data.items():\n print(f\"{address}: {data.get('symbol', 'Unknown')} - {data.get('name', 'Unknown')}\")"
20
+ "code": "from adapters.token_adapter.adapter import TokenAdapter\n\n# Initialize adapter (no config needed)\nadapter = TokenAdapter()\n\n# List of token addresses to lookup (Base chain)\ntoken_addresses = [\n \"0x1234567890abcdef1234567890abcdef12345678\",\n \"0xabcdef1234567890abcdef1234567890abcdef12\",\n \"0x9876543210fedcba9876543210fedcba98765432\"\n]\n\n# Batch lookup\ntoken_data = {}\nfor address in token_addresses:\n success, data = await adapter.get_token(address, chain_id=8453)\n if success:\n token_data[address] = data\n else:\n print(f\"Failed to get token for {address}: {data}\")\n\nprint(f\"Successfully retrieved {len(token_data)} tokens\")\nfor address, data in token_data.items():\n print(f\"{address}: {data.get('symbol', 'Unknown')} - {data.get('name', 'Unknown')}\")"
25
21
  }
26
22
  }
@@ -33,7 +33,7 @@ class TestTokenAdapter:
33
33
  ):
34
34
  success, data = await adapter.get_token("0x1234...")
35
35
 
36
- assert success is True
36
+ assert success
37
37
  assert data == mock_token_data
38
38
 
39
39
  @pytest.mark.asyncio
@@ -55,7 +55,7 @@ class TestTokenAdapter:
55
55
  ):
56
56
  success, data = await adapter.get_token("token-123")
57
57
 
58
- assert success is True
58
+ assert success
59
59
  assert data == mock_token_data
60
60
 
61
61
  def test_adapter_type(self, adapter):
@@ -68,9 +68,8 @@ class TestTokenAdapter:
68
68
  mock_token_data = {
69
69
  "current_price": 1.50,
70
70
  "price_change_24h": 0.05,
71
- "price_change_percentage_24h": 3.45,
72
71
  "market_cap": 1000000,
73
- "total_volume": 50000,
72
+ "total_volume_usd_24h": 50000,
74
73
  "symbol": "TEST",
75
74
  "name": "Test Token",
76
75
  "address": "0x1234...",
@@ -81,10 +80,12 @@ class TestTokenAdapter:
81
80
  ):
82
81
  success, data = await adapter.get_token_price("test-token")
83
82
 
84
- assert success is True
83
+ assert success
85
84
  assert data["current_price"] == 1.50
86
85
  assert data["symbol"] == "TEST"
87
86
  assert data["name"] == "Test Token"
87
+ assert data["total_volume"] == 50000
88
+ assert data["price_change_percentage_24h"] == 5.0 # 0.05 * 100
88
89
 
89
90
  @pytest.mark.asyncio
90
91
  async def test_get_token_price_not_found(self, adapter):
@@ -99,7 +100,8 @@ class TestTokenAdapter:
99
100
  async def test_get_gas_token_success(self, adapter):
100
101
  """Test successful gas token retrieval"""
101
102
  mock_gas_token_data = {
102
- "id": "ethereum-base",
103
+ "id": "ethereum_0x0000000000000000000000000000000000000000",
104
+ "token_id": "ethereum_0x0000000000000000000000000000000000000000",
103
105
  "symbol": "ETH",
104
106
  "name": "Ethereum",
105
107
  "address": "0x0000000000000000000000000000000000000000",
@@ -111,7 +113,7 @@ class TestTokenAdapter:
111
113
  ):
112
114
  success, data = await adapter.get_gas_token("base")
113
115
 
114
- assert success is True
116
+ assert success
115
117
  assert data["symbol"] == "ETH"
116
118
  assert data["name"] == "Ethereum"
117
119
 
@@ -1,6 +1,6 @@
1
1
  """
2
2
  BRAP (Bridge/Router/Adapter Protocol) Client
3
- Provides access to quote operations via the public quote endpoint.
3
+ Provides access to quote operations via the blockchain quote endpoint.
4
4
  """
5
5
 
6
6
  from __future__ import annotations
@@ -10,100 +10,141 @@ from typing import Any, NotRequired, Required, TypedDict
10
10
 
11
11
  from loguru import logger
12
12
 
13
- from wayfinder_paths.core.clients.AuthClient import AuthClient
14
13
  from wayfinder_paths.core.clients.WayfinderClient import WayfinderClient
15
14
  from wayfinder_paths.core.config import get_api_base_url
16
15
 
17
16
 
18
- class BRAPQuote(TypedDict):
17
+ class QuoteTx(TypedDict, total=False):
18
+ """Quote transaction data structure"""
19
+
20
+ data: str
21
+ to: str
22
+ value: str
23
+ chainId: int
24
+
25
+
26
+ class QuoteData(TypedDict):
27
+ """Quote data structure"""
28
+
29
+ gas: Required[str]
30
+ amountOut: Required[str]
31
+ priceImpact: Required[int]
32
+ feeAmount: Required[list[str]]
33
+ minAmountOut: Required[str]
34
+ createdAt: Required[int]
35
+ tx: Required[QuoteTx]
36
+ route: Required[list[dict[str, Any]]]
37
+
38
+
39
+ class FeeBreakdown(TypedDict):
40
+ """Fee breakdown structure"""
41
+
42
+ name: Required[str]
43
+ amount: Required[int]
44
+ amount_usd: Required[float]
45
+ token: Required[str]
46
+ token_chain: Required[int]
47
+
48
+
49
+ class FeeEstimate(TypedDict):
50
+ """Fee estimate structure"""
51
+
52
+ fee_total_usd: Required[float]
53
+ fee_breakdown: Required[list[FeeBreakdown]]
54
+
55
+
56
+ class Calldata(TypedDict, total=False):
57
+ """Calldata structure"""
58
+
59
+ data: str
60
+ to: str
61
+ value: str
62
+ chainId: int
63
+
64
+
65
+ class BRAPQuoteEntry(TypedDict):
66
+ """BRAP quote entry structure"""
67
+
68
+ provider: Required[str]
69
+ quote: Required[QuoteData]
70
+ calldata: Required[Calldata]
71
+ output_amount: Required[int]
72
+ input_amount: Required[int]
73
+ gas_estimate: NotRequired[int | None]
74
+ error: NotRequired[str | None]
75
+ input_amount_usd: Required[float]
76
+ output_amount_usd: Required[float]
77
+ fee_estimate: Required[FeeEstimate]
78
+ wrap_transaction: NotRequired[dict[str, Any] | None]
79
+ unwrap_transaction: NotRequired[dict[str, Any] | None]
80
+ native_input: Required[bool]
81
+ native_output: Required[bool]
82
+
83
+
84
+ class BRAPQuoteResponse(TypedDict):
19
85
  """BRAP quote response structure"""
20
86
 
21
- from_token_address: Required[str]
22
- to_token_address: Required[str]
23
- from_chain_id: Required[int]
24
- to_chain_id: Required[int]
25
- from_address: Required[str]
26
- to_address: Required[str]
27
- amount1: Required[str]
28
- amount2: NotRequired[str]
29
- routes: NotRequired[list[dict[str, Any]]]
30
- best_route: NotRequired[dict[str, Any]]
31
- fees: NotRequired[dict[str, Any] | None]
32
- slippage: NotRequired[float | None]
33
- wayfinder_fee: NotRequired[float | None]
87
+ quotes: Required[list[BRAPQuoteEntry]]
88
+ best_quote: Required[BRAPQuoteEntry]
34
89
 
35
90
 
36
91
  class BRAPClient(WayfinderClient):
37
92
  """Client for BRAP quote operations"""
38
93
 
39
- def __init__(self, api_key: str | None = None):
40
- super().__init__(api_key=api_key)
41
- self.api_base_url = get_api_base_url()
42
- self._auth_client: AuthClient | None = AuthClient(api_key=api_key)
94
+ def __init__(self):
95
+ super().__init__()
96
+ self.api_base_url = f"{get_api_base_url()}/v1/blockchain/braps"
43
97
 
44
98
  async def get_quote(
45
99
  self,
46
100
  *,
47
- from_token_address: str,
48
- to_token_address: str,
49
- from_chain_id: int,
50
- to_chain_id: int,
51
- from_address: str,
52
- to_address: str,
53
- amount1: str,
54
- slippage: float | None = None,
55
- wayfinder_fee: float | None = None,
56
- ) -> BRAPQuote:
101
+ from_token: str,
102
+ to_token: str,
103
+ from_chain: int,
104
+ to_chain: int,
105
+ from_wallet: str,
106
+ from_amount: str,
107
+ ) -> BRAPQuoteResponse: # type: ignore # noqa: E501
57
108
  """
58
109
  Get a quote for a bridge/swap operation.
59
110
 
60
111
  Args:
61
- from_token_address: Source token contract address
62
- to_token_address: Destination token contract address
63
- from_chain_id: Source chain ID
64
- to_chain_id: Destination chain ID
65
- from_address: Source wallet address
66
- to_address: Destination wallet address
67
- amount1: Amount to swap (in smallest units)
68
- slippage: Maximum slippage tolerance (optional)
69
- wayfinder_fee: Wayfinder fee (optional)
112
+ from_token: Source token contract address
113
+ to_token: Destination token contract address
114
+ from_chain: Source chain ID
115
+ to_chain: Destination chain ID
116
+ from_wallet: Source wallet address
117
+ from_amount: Amount to swap (in smallest units)
70
118
 
71
119
  Returns:
72
- Quote data including routes, amounts, fees, etc.
120
+ Quote response including quotes array and best_quote
73
121
  """
74
122
  logger.info(
75
- f"Getting BRAP quote: {from_token_address} -> {to_token_address} (chain {from_chain_id} -> {to_chain_id})"
76
- )
77
- logger.debug(
78
- f"Quote params: amount={amount1}, slippage={slippage}, wayfinder_fee={wayfinder_fee}"
123
+ f"Getting BRAP quote: {from_token} -> {to_token} (chain {from_chain} -> {to_chain})"
79
124
  )
125
+ logger.debug(f"Quote params: amount={from_amount}")
80
126
  start_time = time.time()
81
127
 
82
- url = f"{self.api_base_url}/public/quotes/"
128
+ url = f"{self.api_base_url}/quote/"
83
129
 
84
- payload = {
85
- "from_token_address": from_token_address,
86
- "to_token_address": to_token_address,
87
- "from_chain_id": from_chain_id,
88
- "to_chain_id": to_chain_id,
89
- "from_address": from_address,
90
- "to_address": to_address,
91
- "amount1": amount1,
130
+ params: dict[str, Any] = {
131
+ "from_token": from_token,
132
+ "to_token": to_token,
133
+ "from_chain": from_chain,
134
+ "to_chain": to_chain,
135
+ "from_wallet": from_wallet,
136
+ "from_amount": from_amount,
92
137
  }
93
138
 
94
- # Only add optional parameters if they're provided
95
- if slippage is not None:
96
- payload["slippage"] = slippage
97
- if wayfinder_fee is not None:
98
- payload["wayfinder_fee"] = wayfinder_fee
99
-
100
139
  try:
101
- response = await self._request("POST", url, json=payload, headers={})
140
+ response = await self._authed_request("GET", url, params=params, headers={})
102
141
  response.raise_for_status()
103
142
  data = response.json()
143
+ result = data.get("data", data)
144
+
104
145
  elapsed = time.time() - start_time
105
146
  logger.info(f"BRAP quote request completed successfully in {elapsed:.2f}s")
106
- return data.get("data", data)
147
+ return result
107
148
  except Exception as e:
108
149
  elapsed = time.time() - start_time
109
150
  logger.error(f"BRAP quote request failed after {elapsed:.2f}s: {e}")
@@ -5,7 +5,6 @@ Consolidated client management for all API interactions
5
5
 
6
6
  from typing import Any
7
7
 
8
- from wayfinder_paths.core.clients.AuthClient import AuthClient
9
8
  from wayfinder_paths.core.clients.BRAPClient import BRAPClient
10
9
  from wayfinder_paths.core.clients.HyperlendClient import HyperlendClient
11
10
  from wayfinder_paths.core.clients.LedgerClient import LedgerClient
@@ -37,7 +36,6 @@ class ClientManager:
37
36
  self,
38
37
  clients: dict[str, Any] | None = None,
39
38
  skip_auth: bool = False,
40
- api_key: str | None = None,
41
39
  ):
42
40
  """
43
41
  Initialize ClientManager.
@@ -45,14 +43,10 @@ class ClientManager:
45
43
  Args:
46
44
  clients: Optional dict of pre-instantiated clients to inject directly.
47
45
  skip_auth: If True, skips authentication (for SDK usage).
48
- api_key: Optional API key for service account authentication.
49
46
  """
50
47
  self._injected_clients = clients or {}
51
48
  self._skip_auth = skip_auth
52
- self._api_key = api_key
53
- self._access_token: str | None = None
54
49
 
55
- self._auth_client: AuthClient | None = None
56
50
  self._token_client: TokenClientProtocol | None = None
57
51
  self._wallet_client: WalletClientProtocol | None = None
58
52
  self._ledger_client: LedgerClientProtocol | None = None
@@ -79,25 +73,10 @@ class ClientManager:
79
73
  """
80
74
  client = getattr(self, client_attr)
81
75
  if not client:
82
- client = self._injected_clients.get(injected_key) or client_class(
83
- api_key=self._api_key
84
- )
76
+ client = self._injected_clients.get(injected_key) or client_class()
85
77
  setattr(self, client_attr, client)
86
- if self._access_token and hasattr(client, "set_bearer_token"):
87
- client.set_bearer_token(self._access_token)
88
78
  return client
89
79
 
90
- @property
91
- def auth(self) -> AuthClient | None:
92
- """Get or create auth client. Returns None if skip_auth=True."""
93
- if self._skip_auth:
94
- return None
95
- if not self._auth_client:
96
- self._auth_client = AuthClient(api_key=self._api_key)
97
- if self._access_token:
98
- self._auth_client.set_bearer_token(self._access_token)
99
- return self._auth_client
100
-
101
80
  @property
102
81
  def token(self) -> TokenClientProtocol:
103
82
  """Get or create token client"""
@@ -130,55 +109,9 @@ class ClientManager:
130
109
  """Get or create BRAP client"""
131
110
  return self._get_or_create_client("_brap_client", "brap", BRAPClient)
132
111
 
133
- async def authenticate(
134
- self,
135
- username: str | None = None,
136
- password: str | None = None,
137
- *,
138
- refresh_token: str | None = None,
139
- ) -> dict[str, Any]:
140
- """Authenticate with the API. Raises ValueError if skip_auth=True."""
141
- if self._skip_auth:
142
- raise ValueError(
143
- "Authentication is disabled in SDK mode. SDK users handle their own authentication."
144
- )
145
- auth_client = self.auth
146
- if auth_client is None:
147
- raise ValueError("Auth client is not available")
148
- data = await auth_client.authenticate(
149
- username, password, refresh_token=refresh_token
150
- )
151
- access = data.get("access") or data.get("access_token")
152
- if access:
153
- self.set_access_token(access)
154
- return data
155
-
156
- def set_access_token(self, access_token: str) -> None:
157
- """Set and propagate access token to all initialized clients."""
158
- self._access_token = access_token
159
- if self._auth_client:
160
- self._auth_client.set_bearer_token(access_token)
161
- if self._token_client and hasattr(self._token_client, "set_bearer_token"):
162
- self._token_client.set_bearer_token(access_token)
163
- if self._transaction_client and hasattr(
164
- self._transaction_client, "set_bearer_token"
165
- ):
166
- self._transaction_client.set_bearer_token(access_token)
167
- if self._ledger_client and hasattr(self._ledger_client, "set_bearer_token"):
168
- self._ledger_client.set_bearer_token(access_token)
169
- if self._pool_client and hasattr(self._pool_client, "set_bearer_token"):
170
- self._pool_client.set_bearer_token(access_token)
171
- if self._hyperlend_client and hasattr(
172
- self._hyperlend_client, "set_bearer_token"
173
- ):
174
- self._hyperlend_client.set_bearer_token(access_token)
175
- if self._wallet_client and hasattr(self._wallet_client, "set_bearer_token"):
176
- self._wallet_client.set_bearer_token(access_token)
177
-
178
112
  def get_all_clients(self) -> dict[str, Any]:
179
113
  """Get all initialized clients for direct access"""
180
114
  return {
181
- "auth": self._auth_client,
182
115
  "token": self._token_client,
183
116
  "transaction": self._transaction_client,
184
117
  "ledger": self._ledger_client,