wayfinder-paths 0.1.4__py3-none-any.whl → 0.1.5__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.
- wayfinder_paths/CONFIG_GUIDE.md +14 -14
- wayfinder_paths/__init__.py +3 -3
- wayfinder_paths/adapters/balance_adapter/README.md +10 -10
- wayfinder_paths/adapters/balance_adapter/adapter.py +10 -9
- wayfinder_paths/adapters/balance_adapter/examples.json +1 -1
- wayfinder_paths/adapters/brap_adapter/README.md +1 -1
- wayfinder_paths/adapters/brap_adapter/adapter.py +28 -21
- wayfinder_paths/adapters/hyperlend_adapter/adapter.py +33 -26
- wayfinder_paths/adapters/ledger_adapter/README.md +26 -39
- wayfinder_paths/adapters/ledger_adapter/adapter.py +78 -75
- wayfinder_paths/adapters/ledger_adapter/examples.json +10 -4
- wayfinder_paths/adapters/ledger_adapter/manifest.yaml +4 -4
- wayfinder_paths/adapters/ledger_adapter/test_adapter.py +31 -26
- wayfinder_paths/adapters/pool_adapter/README.md +1 -13
- wayfinder_paths/adapters/pool_adapter/adapter.py +12 -19
- wayfinder_paths/adapters/token_adapter/adapter.py +8 -4
- wayfinder_paths/core/__init__.py +3 -3
- wayfinder_paths/core/adapters/BaseAdapter.py +20 -3
- wayfinder_paths/core/adapters/models.py +41 -0
- wayfinder_paths/core/clients/BRAPClient.py +21 -2
- wayfinder_paths/core/clients/ClientManager.py +42 -63
- wayfinder_paths/core/clients/HyperlendClient.py +46 -5
- wayfinder_paths/core/clients/LedgerClient.py +350 -124
- wayfinder_paths/core/clients/PoolClient.py +51 -19
- wayfinder_paths/core/clients/SimulationClient.py +16 -4
- wayfinder_paths/core/clients/TokenClient.py +34 -18
- wayfinder_paths/core/clients/TransactionClient.py +18 -2
- wayfinder_paths/core/clients/WalletClient.py +35 -4
- wayfinder_paths/core/clients/WayfinderClient.py +16 -5
- wayfinder_paths/core/clients/protocols.py +69 -62
- wayfinder_paths/core/clients/sdk_example.py +0 -5
- wayfinder_paths/core/config.py +192 -103
- wayfinder_paths/core/constants/base.py +17 -0
- wayfinder_paths/core/engine/{VaultJob.py → StrategyJob.py} +25 -19
- wayfinder_paths/core/engine/__init__.py +2 -2
- wayfinder_paths/core/services/base.py +6 -4
- wayfinder_paths/core/services/local_evm_txn.py +3 -2
- wayfinder_paths/core/settings.py +2 -2
- wayfinder_paths/core/strategies/Strategy.py +123 -37
- wayfinder_paths/core/utils/evm_helpers.py +12 -10
- wayfinder_paths/core/wallets/README.md +3 -3
- wayfinder_paths/core/wallets/WalletManager.py +3 -3
- wayfinder_paths/run_strategy.py +26 -24
- wayfinder_paths/scripts/make_wallets.py +6 -6
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/README.md +6 -6
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +36 -156
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +6 -6
- wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +11 -11
- wayfinder_paths/strategies/stablecoin_yield_strategy/manifest.yaml +1 -1
- wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +92 -92
- wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +6 -6
- wayfinder_paths/templates/adapter/README.md +1 -1
- wayfinder_paths/templates/adapter/test_adapter.py +1 -1
- wayfinder_paths/templates/strategy/README.md +4 -4
- wayfinder_paths/templates/strategy/test_strategy.py +7 -7
- wayfinder_paths/tests/test_test_coverage.py +5 -5
- {wayfinder_paths-0.1.4.dist-info → wayfinder_paths-0.1.5.dist-info}/METADATA +46 -47
- {wayfinder_paths-0.1.4.dist-info → wayfinder_paths-0.1.5.dist-info}/RECORD +60 -59
- {wayfinder_paths-0.1.4.dist-info → wayfinder_paths-0.1.5.dist-info}/LICENSE +0 -0
- {wayfinder_paths-0.1.4.dist-info → wayfinder_paths-0.1.5.dist-info}/WHEEL +0 -0
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
|
|
3
3
|
from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
|
|
4
|
-
from wayfinder_paths.core.clients.PoolClient import
|
|
4
|
+
from wayfinder_paths.core.clients.PoolClient import (
|
|
5
|
+
LlamaMatch,
|
|
6
|
+
LlamaReport,
|
|
7
|
+
PoolClient,
|
|
8
|
+
PoolList,
|
|
9
|
+
)
|
|
5
10
|
|
|
6
11
|
|
|
7
12
|
class PoolAdapter(BaseAdapter):
|
|
@@ -27,7 +32,7 @@ class PoolAdapter(BaseAdapter):
|
|
|
27
32
|
|
|
28
33
|
async def get_pools_by_ids(
|
|
29
34
|
self, pool_ids: list[str], merge_external: bool | None = None
|
|
30
|
-
) -> tuple[bool,
|
|
35
|
+
) -> tuple[bool, PoolList | str]:
|
|
31
36
|
"""
|
|
32
37
|
Get pool information by pool IDs.
|
|
33
38
|
|
|
@@ -50,7 +55,7 @@ class PoolAdapter(BaseAdapter):
|
|
|
50
55
|
|
|
51
56
|
async def get_all_pools(
|
|
52
57
|
self, merge_external: bool | None = None
|
|
53
|
-
) -> tuple[bool,
|
|
58
|
+
) -> tuple[bool, PoolList | str]:
|
|
54
59
|
"""
|
|
55
60
|
Get all available pools.
|
|
56
61
|
|
|
@@ -67,21 +72,7 @@ class PoolAdapter(BaseAdapter):
|
|
|
67
72
|
self.logger.error(f"Error fetching all pools: {e}")
|
|
68
73
|
return (False, str(e))
|
|
69
74
|
|
|
70
|
-
async def
|
|
71
|
-
"""
|
|
72
|
-
Get combined pool reports with analytics.
|
|
73
|
-
|
|
74
|
-
Returns:
|
|
75
|
-
Tuple of (success, data) where data is combined reports or error message
|
|
76
|
-
"""
|
|
77
|
-
try:
|
|
78
|
-
data = await self.pool_client.get_combined_pool_reports()
|
|
79
|
-
return (True, data)
|
|
80
|
-
except Exception as e:
|
|
81
|
-
self.logger.error(f"Error fetching combined pool reports: {e}")
|
|
82
|
-
return (False, str(e))
|
|
83
|
-
|
|
84
|
-
async def get_llama_matches(self) -> tuple[bool, Any]:
|
|
75
|
+
async def get_llama_matches(self) -> tuple[bool, dict[str, LlamaMatch] | str]:
|
|
85
76
|
"""
|
|
86
77
|
Get Llama protocol matches for pools.
|
|
87
78
|
|
|
@@ -95,7 +86,9 @@ class PoolAdapter(BaseAdapter):
|
|
|
95
86
|
self.logger.error(f"Error fetching Llama matches: {e}")
|
|
96
87
|
return (False, str(e))
|
|
97
88
|
|
|
98
|
-
async def get_llama_reports(
|
|
89
|
+
async def get_llama_reports(
|
|
90
|
+
self, identifiers: list[str]
|
|
91
|
+
) -> tuple[bool, dict[str, LlamaReport] | str]:
|
|
99
92
|
"""
|
|
100
93
|
Get Llama reports for specific identifiers.
|
|
101
94
|
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
|
|
3
3
|
from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
|
|
4
|
-
from wayfinder_paths.core.clients.TokenClient import
|
|
4
|
+
from wayfinder_paths.core.clients.TokenClient import (
|
|
5
|
+
GasToken,
|
|
6
|
+
TokenClient,
|
|
7
|
+
TokenDetails,
|
|
8
|
+
)
|
|
5
9
|
|
|
6
10
|
|
|
7
11
|
class TokenAdapter(BaseAdapter):
|
|
@@ -20,7 +24,7 @@ class TokenAdapter(BaseAdapter):
|
|
|
20
24
|
super().__init__("token_adapter", config)
|
|
21
25
|
self.token_client = token_client or TokenClient()
|
|
22
26
|
|
|
23
|
-
async def get_token(self, query: str) -> tuple[bool,
|
|
27
|
+
async def get_token(self, query: str) -> tuple[bool, TokenDetails | str]:
|
|
24
28
|
"""
|
|
25
29
|
Get token data by address using the token-details endpoint.
|
|
26
30
|
|
|
@@ -39,7 +43,7 @@ class TokenAdapter(BaseAdapter):
|
|
|
39
43
|
self.logger.error(f"Error getting token by query {query}: {e}")
|
|
40
44
|
return (False, str(e))
|
|
41
45
|
|
|
42
|
-
async def get_token_price(self, token_id: str) -> tuple[bool, Any]:
|
|
46
|
+
async def get_token_price(self, token_id: str) -> tuple[bool, dict[str, Any] | str]:
|
|
43
47
|
"""
|
|
44
48
|
Get token price by token ID or address using the token-details endpoint.
|
|
45
49
|
|
|
@@ -72,7 +76,7 @@ class TokenAdapter(BaseAdapter):
|
|
|
72
76
|
self.logger.error(f"Error getting token price for {token_id}: {e}")
|
|
73
77
|
return (False, str(e))
|
|
74
78
|
|
|
75
|
-
async def get_gas_token(self, chain_code: str) -> tuple[bool,
|
|
79
|
+
async def get_gas_token(self, chain_code: str) -> tuple[bool, GasToken | str]:
|
|
76
80
|
"""
|
|
77
81
|
Get gas token for a given chain code.
|
|
78
82
|
|
wayfinder_paths/core/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"""Wayfinder
|
|
1
|
+
"""Wayfinder Paths Core Engine"""
|
|
2
2
|
|
|
3
3
|
from wayfinder_paths.core.adapters.BaseAdapter import BaseAdapter
|
|
4
|
-
from wayfinder_paths.core.engine.
|
|
4
|
+
from wayfinder_paths.core.engine.StrategyJob import StrategyJob
|
|
5
5
|
from wayfinder_paths.core.strategies.Strategy import StatusDict, StatusTuple, Strategy
|
|
6
6
|
|
|
7
7
|
__all__ = [
|
|
@@ -9,5 +9,5 @@ __all__ = [
|
|
|
9
9
|
"StatusDict",
|
|
10
10
|
"StatusTuple",
|
|
11
11
|
"BaseAdapter",
|
|
12
|
-
"
|
|
12
|
+
"StrategyJob",
|
|
13
13
|
]
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from abc import ABC
|
|
2
4
|
from typing import Any
|
|
3
5
|
|
|
@@ -7,7 +9,7 @@ from loguru import logger
|
|
|
7
9
|
class BaseAdapter(ABC):
|
|
8
10
|
"""Base adapter class for exchange/protocol integrations"""
|
|
9
11
|
|
|
10
|
-
adapter_type: str = None
|
|
12
|
+
adapter_type: str | None = None
|
|
11
13
|
|
|
12
14
|
def __init__(self, name: str, config: dict[str, Any] | None = None):
|
|
13
15
|
self.name = name
|
|
@@ -19,7 +21,22 @@ class BaseAdapter(ABC):
|
|
|
19
21
|
return True
|
|
20
22
|
|
|
21
23
|
async def get_balance(self, asset: str) -> dict[str, Any]:
|
|
22
|
-
"""
|
|
24
|
+
"""
|
|
25
|
+
Get balance for an asset.
|
|
26
|
+
Optional method that can be overridden by subclasses.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
asset: Asset identifier (token address, token ID, etc.).
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
Dictionary containing balance information.
|
|
33
|
+
|
|
34
|
+
Raises:
|
|
35
|
+
ValueError: If asset is empty or invalid.
|
|
36
|
+
NotImplementedError: If this adapter does not support balance queries.
|
|
37
|
+
"""
|
|
38
|
+
if not asset or not isinstance(asset, str) or not asset.strip():
|
|
39
|
+
raise ValueError("asset must be a non-empty string")
|
|
23
40
|
raise NotImplementedError(
|
|
24
41
|
f"get_balance not supported by {self.__class__.__name__}"
|
|
25
42
|
)
|
|
@@ -43,6 +60,6 @@ class BaseAdapter(ABC):
|
|
|
43
60
|
"adapter": self.adapter_type or self.__class__.__name__,
|
|
44
61
|
}
|
|
45
62
|
|
|
46
|
-
async def close(self):
|
|
63
|
+
async def close(self) -> None:
|
|
47
64
|
"""Clean up resources"""
|
|
48
65
|
pass
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Pydantic models for ledger operations."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated, Any, Literal
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SWAP(BaseModel):
|
|
9
|
+
"""Swap operation."""
|
|
10
|
+
|
|
11
|
+
type: Literal["SWAP"] = "SWAP"
|
|
12
|
+
from_token_id: str
|
|
13
|
+
to_token_id: str
|
|
14
|
+
from_amount: str
|
|
15
|
+
to_amount: str
|
|
16
|
+
from_amount_usd: float
|
|
17
|
+
to_amount_usd: float
|
|
18
|
+
transaction_hash: str | None = None
|
|
19
|
+
transaction_status: str | None = None
|
|
20
|
+
transaction_receipt: dict[str, Any] | None = None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class LEND(BaseModel):
|
|
24
|
+
type: Literal["LEND"] = "LEND"
|
|
25
|
+
contract: str
|
|
26
|
+
amount: int
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class UNLEND(BaseModel):
|
|
30
|
+
type: Literal["UNLEND"] = "UNLEND"
|
|
31
|
+
contract: str
|
|
32
|
+
amount: int
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# Type alias for operation types (currently only SWAP is used)
|
|
36
|
+
# Add more operation types here as needed
|
|
37
|
+
Operation = SWAP | LEND | UNLEND
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class STRAT_OP(BaseModel):
|
|
41
|
+
op_data: Annotated[Operation, Field(discriminator="type")]
|
|
@@ -3,8 +3,10 @@ BRAP (Bridge/Router/Adapter Protocol) Client
|
|
|
3
3
|
Provides access to quote operations via the public quote endpoint.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
6
8
|
import time
|
|
7
|
-
from typing import Any
|
|
9
|
+
from typing import Any, NotRequired, Required, TypedDict
|
|
8
10
|
|
|
9
11
|
from loguru import logger
|
|
10
12
|
|
|
@@ -13,6 +15,23 @@ from wayfinder_paths.core.clients.WayfinderClient import WayfinderClient
|
|
|
13
15
|
from wayfinder_paths.core.settings import settings
|
|
14
16
|
|
|
15
17
|
|
|
18
|
+
class BRAPQuote(TypedDict):
|
|
19
|
+
"""BRAP quote response structure"""
|
|
20
|
+
|
|
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
|
+
fees: NotRequired[dict[str, Any] | None]
|
|
31
|
+
slippage: NotRequired[float | None]
|
|
32
|
+
wayfinder_fee: NotRequired[float | None]
|
|
33
|
+
|
|
34
|
+
|
|
16
35
|
class BRAPClient(WayfinderClient):
|
|
17
36
|
"""Client for BRAP quote operations"""
|
|
18
37
|
|
|
@@ -33,7 +52,7 @@ class BRAPClient(WayfinderClient):
|
|
|
33
52
|
amount1: str,
|
|
34
53
|
slippage: float | None = None,
|
|
35
54
|
wayfinder_fee: float | None = None,
|
|
36
|
-
) ->
|
|
55
|
+
) -> BRAPQuote:
|
|
37
56
|
"""
|
|
38
57
|
Get a quote for a bridge/swap operation.
|
|
39
58
|
|
|
@@ -28,7 +28,7 @@ from wayfinder_paths.core.clients.WalletClient import WalletClient
|
|
|
28
28
|
|
|
29
29
|
class ClientManager:
|
|
30
30
|
"""
|
|
31
|
-
Manages all API client instances for a
|
|
31
|
+
Manages all API client instances for a strategy job.
|
|
32
32
|
|
|
33
33
|
Args:
|
|
34
34
|
clients: Optional dict of pre-instantiated clients to inject directly.
|
|
@@ -66,6 +66,33 @@ class ClientManager:
|
|
|
66
66
|
self._brap_client: BRAPClientProtocol | None = None
|
|
67
67
|
self._simulation_client: SimulationClientProtocol | None = None
|
|
68
68
|
|
|
69
|
+
def _get_or_create_client(
|
|
70
|
+
self,
|
|
71
|
+
client_attr: str,
|
|
72
|
+
injected_key: str,
|
|
73
|
+
client_class: type[Any],
|
|
74
|
+
) -> Any:
|
|
75
|
+
"""
|
|
76
|
+
Helper method to get or create a client instance.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
client_attr: Name of the private attribute storing the client (e.g., "_token_client").
|
|
80
|
+
injected_key: Key to look up in _injected_clients dict.
|
|
81
|
+
client_class: Client class to instantiate if not injected.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Client instance.
|
|
85
|
+
"""
|
|
86
|
+
client = getattr(self, client_attr)
|
|
87
|
+
if not client:
|
|
88
|
+
client = self._injected_clients.get(injected_key) or client_class(
|
|
89
|
+
api_key=self._api_key
|
|
90
|
+
)
|
|
91
|
+
setattr(self, client_attr, client)
|
|
92
|
+
if self._access_token and hasattr(client, "set_bearer_token"):
|
|
93
|
+
client.set_bearer_token(self._access_token)
|
|
94
|
+
return client
|
|
95
|
+
|
|
69
96
|
@property
|
|
70
97
|
def auth(self) -> AuthClient | None:
|
|
71
98
|
"""Get or create auth client. Returns None if skip_auth=True."""
|
|
@@ -80,96 +107,48 @@ class ClientManager:
|
|
|
80
107
|
@property
|
|
81
108
|
def token(self) -> TokenClientProtocol:
|
|
82
109
|
"""Get or create token client"""
|
|
83
|
-
|
|
84
|
-
self._token_client = self._injected_clients.get("token") or TokenClient(
|
|
85
|
-
api_key=self._api_key
|
|
86
|
-
)
|
|
87
|
-
if self._access_token and hasattr(self._token_client, "set_bearer_token"):
|
|
88
|
-
self._token_client.set_bearer_token(self._access_token)
|
|
89
|
-
return self._token_client
|
|
110
|
+
return self._get_or_create_client("_token_client", "token", TokenClient)
|
|
90
111
|
|
|
91
112
|
@property
|
|
92
113
|
def transaction(self) -> TransactionClientProtocol:
|
|
93
114
|
"""Get or create transaction client"""
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
) or TransactionClient(api_key=self._api_key)
|
|
98
|
-
if self._access_token and hasattr(
|
|
99
|
-
self._transaction_client, "set_bearer_token"
|
|
100
|
-
):
|
|
101
|
-
self._transaction_client.set_bearer_token(self._access_token)
|
|
102
|
-
return self._transaction_client
|
|
115
|
+
return self._get_or_create_client(
|
|
116
|
+
"_transaction_client", "transaction", TransactionClient
|
|
117
|
+
)
|
|
103
118
|
|
|
104
119
|
@property
|
|
105
120
|
def ledger(self) -> LedgerClientProtocol:
|
|
106
121
|
"""Get or create ledger client"""
|
|
107
|
-
|
|
108
|
-
self._ledger_client = self._injected_clients.get("ledger") or LedgerClient(
|
|
109
|
-
api_key=self._api_key
|
|
110
|
-
)
|
|
111
|
-
if self._access_token and hasattr(self._ledger_client, "set_bearer_token"):
|
|
112
|
-
self._ledger_client.set_bearer_token(self._access_token)
|
|
113
|
-
return self._ledger_client
|
|
122
|
+
return self._get_or_create_client("_ledger_client", "ledger", LedgerClient)
|
|
114
123
|
|
|
115
124
|
@property
|
|
116
125
|
def pool(self) -> PoolClientProtocol:
|
|
117
126
|
"""Get or create pool client"""
|
|
118
|
-
|
|
119
|
-
self._pool_client = self._injected_clients.get("pool") or PoolClient(
|
|
120
|
-
api_key=self._api_key
|
|
121
|
-
)
|
|
122
|
-
if self._access_token and hasattr(self._pool_client, "set_bearer_token"):
|
|
123
|
-
self._pool_client.set_bearer_token(self._access_token)
|
|
124
|
-
return self._pool_client
|
|
127
|
+
return self._get_or_create_client("_pool_client", "pool", PoolClient)
|
|
125
128
|
|
|
126
129
|
@property
|
|
127
130
|
def hyperlend(self) -> HyperlendClientProtocol:
|
|
128
131
|
"""Get or create hyperlend client"""
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
) or HyperlendClient(api_key=self._api_key)
|
|
133
|
-
if self._access_token and hasattr(
|
|
134
|
-
self._hyperlend_client, "set_bearer_token"
|
|
135
|
-
):
|
|
136
|
-
self._hyperlend_client.set_bearer_token(self._access_token)
|
|
137
|
-
return self._hyperlend_client
|
|
132
|
+
return self._get_or_create_client(
|
|
133
|
+
"_hyperlend_client", "hyperlend", HyperlendClient
|
|
134
|
+
)
|
|
138
135
|
|
|
139
136
|
@property
|
|
140
137
|
def wallet(self) -> WalletClientProtocol:
|
|
141
138
|
"""Get or create wallet client"""
|
|
142
|
-
|
|
143
|
-
self._wallet_client = self._injected_clients.get("wallet") or WalletClient(
|
|
144
|
-
api_key=self._api_key
|
|
145
|
-
)
|
|
146
|
-
if self._access_token and hasattr(self._wallet_client, "set_bearer_token"):
|
|
147
|
-
self._wallet_client.set_bearer_token(self._access_token)
|
|
148
|
-
return self._wallet_client
|
|
139
|
+
return self._get_or_create_client("_wallet_client", "wallet", WalletClient)
|
|
149
140
|
|
|
150
141
|
@property
|
|
151
142
|
def brap(self) -> BRAPClientProtocol:
|
|
152
143
|
"""Get or create BRAP client"""
|
|
153
|
-
|
|
154
|
-
self._brap_client = self._injected_clients.get("brap") or BRAPClient(
|
|
155
|
-
api_key=self._api_key
|
|
156
|
-
)
|
|
157
|
-
if self._access_token and hasattr(self._brap_client, "set_bearer_token"):
|
|
158
|
-
self._brap_client.set_bearer_token(self._access_token)
|
|
159
|
-
return self._brap_client
|
|
144
|
+
return self._get_or_create_client("_brap_client", "brap", BRAPClient)
|
|
160
145
|
|
|
161
146
|
@property
|
|
162
147
|
def simulation(self) -> SimulationClientProtocol:
|
|
163
148
|
"""Get or create simulation client"""
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
) or SimulationClient(api_key=self._api_key)
|
|
168
|
-
if self._access_token and hasattr(
|
|
169
|
-
self._simulation_client, "set_bearer_token"
|
|
170
|
-
):
|
|
171
|
-
self._simulation_client.set_bearer_token(self._access_token)
|
|
172
|
-
return self._simulation_client
|
|
149
|
+
return self._get_or_create_client(
|
|
150
|
+
"_simulation_client", "simulation", SimulationClient
|
|
151
|
+
)
|
|
173
152
|
|
|
174
153
|
async def authenticate(
|
|
175
154
|
self,
|
|
@@ -3,12 +3,53 @@ Hyperlend Client
|
|
|
3
3
|
Provides access to Hyperlend stable markets data via public endpoints.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Any, NotRequired, Required, TypedDict
|
|
7
9
|
|
|
8
10
|
from wayfinder_paths.core.clients.WayfinderClient import WayfinderClient
|
|
9
11
|
from wayfinder_paths.core.settings import settings
|
|
10
12
|
|
|
11
13
|
|
|
14
|
+
class StableMarket(TypedDict):
|
|
15
|
+
"""Stable market data structure"""
|
|
16
|
+
|
|
17
|
+
chain_id: Required[int]
|
|
18
|
+
token_address: Required[str]
|
|
19
|
+
symbol: Required[str]
|
|
20
|
+
name: Required[str]
|
|
21
|
+
underlying_tokens: Required[float]
|
|
22
|
+
buffer_bps: Required[int]
|
|
23
|
+
min_buffer_tokens: Required[float]
|
|
24
|
+
is_stable_symbol: Required[bool]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class AssetsView(TypedDict):
|
|
28
|
+
"""Assets view response structure"""
|
|
29
|
+
|
|
30
|
+
chain_id: Required[int]
|
|
31
|
+
user_address: Required[str]
|
|
32
|
+
assets: Required[list[dict[str, Any]]]
|
|
33
|
+
total_value: NotRequired[float | None]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class MarketEntry(TypedDict):
|
|
37
|
+
"""Market entry data structure"""
|
|
38
|
+
|
|
39
|
+
chain_id: Required[int]
|
|
40
|
+
token_address: Required[str]
|
|
41
|
+
market_data: Required[dict[str, Any]]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class LendRateHistory(TypedDict):
|
|
45
|
+
"""Lend rate history response structure"""
|
|
46
|
+
|
|
47
|
+
chain_id: Required[int]
|
|
48
|
+
token_address: Required[str]
|
|
49
|
+
lookback_hours: Required[int]
|
|
50
|
+
rates: Required[list[dict[str, Any]]]
|
|
51
|
+
|
|
52
|
+
|
|
12
53
|
class HyperlendClient(WayfinderClient):
|
|
13
54
|
"""Client for Hyperlend-related operations"""
|
|
14
55
|
|
|
@@ -24,7 +65,7 @@ class HyperlendClient(WayfinderClient):
|
|
|
24
65
|
buffer_bps: int | None = None,
|
|
25
66
|
min_buffer_tokens: float | None = None,
|
|
26
67
|
is_stable_symbol: bool | None = None,
|
|
27
|
-
) ->
|
|
68
|
+
) -> list[StableMarket]:
|
|
28
69
|
"""
|
|
29
70
|
Fetch stable markets from Hyperlend.
|
|
30
71
|
|
|
@@ -62,7 +103,7 @@ class HyperlendClient(WayfinderClient):
|
|
|
62
103
|
*,
|
|
63
104
|
chain_id: int,
|
|
64
105
|
user_address: str,
|
|
65
|
-
) ->
|
|
106
|
+
) -> AssetsView:
|
|
66
107
|
"""
|
|
67
108
|
Fetch assets view for a user address from Hyperlend.
|
|
68
109
|
|
|
@@ -92,7 +133,7 @@ class HyperlendClient(WayfinderClient):
|
|
|
92
133
|
*,
|
|
93
134
|
chain_id: int,
|
|
94
135
|
token_address: str,
|
|
95
|
-
) ->
|
|
136
|
+
) -> MarketEntry:
|
|
96
137
|
"""
|
|
97
138
|
Fetch market entry from Hyperlend.
|
|
98
139
|
|
|
@@ -123,7 +164,7 @@ class HyperlendClient(WayfinderClient):
|
|
|
123
164
|
chain_id: int,
|
|
124
165
|
token_address: str,
|
|
125
166
|
lookback_hours: int,
|
|
126
|
-
) ->
|
|
167
|
+
) -> LendRateHistory:
|
|
127
168
|
"""
|
|
128
169
|
Fetch lend rate history from Hyperlend.
|
|
129
170
|
|