wayfinder-paths 0.1.13__py3-none-any.whl → 0.1.14__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/adapters/balance_adapter/README.md +13 -14
- wayfinder_paths/adapters/balance_adapter/adapter.py +33 -32
- wayfinder_paths/adapters/balance_adapter/test_adapter.py +123 -0
- wayfinder_paths/adapters/brap_adapter/README.md +11 -16
- wayfinder_paths/adapters/brap_adapter/adapter.py +78 -63
- wayfinder_paths/adapters/brap_adapter/examples.json +63 -52
- wayfinder_paths/adapters/brap_adapter/test_adapter.py +121 -59
- wayfinder_paths/adapters/hyperlend_adapter/adapter.py +16 -14
- wayfinder_paths/adapters/hyperlend_adapter/test_adapter.py +114 -60
- wayfinder_paths/adapters/pool_adapter/README.md +9 -10
- wayfinder_paths/adapters/pool_adapter/adapter.py +9 -10
- wayfinder_paths/adapters/token_adapter/README.md +2 -14
- wayfinder_paths/adapters/token_adapter/adapter.py +16 -10
- wayfinder_paths/adapters/token_adapter/examples.json +4 -8
- wayfinder_paths/adapters/token_adapter/test_adapter.py +5 -3
- wayfinder_paths/core/clients/BRAPClient.py +102 -61
- wayfinder_paths/core/clients/ClientManager.py +1 -68
- wayfinder_paths/core/clients/HyperlendClient.py +125 -64
- wayfinder_paths/core/clients/LedgerClient.py +1 -4
- wayfinder_paths/core/clients/PoolClient.py +122 -48
- wayfinder_paths/core/clients/TokenClient.py +91 -36
- wayfinder_paths/core/clients/WalletClient.py +26 -56
- wayfinder_paths/core/clients/WayfinderClient.py +28 -160
- wayfinder_paths/core/clients/__init__.py +0 -2
- wayfinder_paths/core/clients/protocols.py +35 -46
- wayfinder_paths/core/clients/sdk_example.py +37 -22
- wayfinder_paths/core/engine/StrategyJob.py +7 -55
- wayfinder_paths/core/services/local_evm_txn.py +6 -6
- wayfinder_paths/core/services/local_token_txn.py +1 -1
- wayfinder_paths/core/strategies/Strategy.py +0 -2
- wayfinder_paths/core/utils/evm_helpers.py +2 -2
- wayfinder_paths/run_strategy.py +8 -19
- wayfinder_paths/strategies/basis_trading_strategy/strategy.py +10 -11
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/strategy.py +40 -25
- wayfinder_paths/strategies/hyperlend_stable_yield_strategy/test_strategy.py +54 -9
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/strategy.py +3 -3
- wayfinder_paths/strategies/moonwell_wsteth_loop_strategy/test_strategy.py +12 -6
- wayfinder_paths/strategies/stablecoin_yield_strategy/README.md +1 -1
- wayfinder_paths/strategies/stablecoin_yield_strategy/strategy.py +88 -56
- wayfinder_paths/strategies/stablecoin_yield_strategy/test_strategy.py +16 -12
- wayfinder_paths/templates/strategy/README.md +3 -3
- wayfinder_paths/templates/strategy/test_strategy.py +3 -2
- {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.14.dist-info}/METADATA +14 -49
- {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.14.dist-info}/RECORD +46 -47
- wayfinder_paths/core/clients/AuthClient.py +0 -83
- {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.14.dist-info}/LICENSE +0 -0
- {wayfinder_paths-0.1.13.dist-info → wayfinder_paths-0.1.14.dist-info}/WHEEL +0 -0
|
@@ -1,76 +1,150 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Pool Client
|
|
3
|
-
Provides read-only access to pool metadata and analytics via public endpoints.
|
|
4
|
-
"""
|
|
1
|
+
"""Read-only pool metadata and analytics via public endpoints."""
|
|
5
2
|
|
|
6
3
|
from __future__ import annotations
|
|
7
4
|
|
|
8
|
-
from typing import Any,
|
|
5
|
+
from typing import Any, Required, TypedDict
|
|
9
6
|
|
|
10
|
-
from wayfinder_paths.core.clients.AuthClient import AuthClient
|
|
11
7
|
from wayfinder_paths.core.clients.WayfinderClient import WayfinderClient
|
|
12
8
|
from wayfinder_paths.core.config import get_api_base_url
|
|
13
9
|
|
|
14
10
|
|
|
15
|
-
class
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
11
|
+
class PoolPredictions(TypedDict, total=False):
|
|
12
|
+
predictedClass: str | None
|
|
13
|
+
predictedProbability: int | None
|
|
14
|
+
binnedConfidence: int | None
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class PoolData(TypedDict, total=False):
|
|
18
|
+
pool: str
|
|
19
|
+
timestamp: str
|
|
20
|
+
project: str
|
|
21
|
+
chain: str
|
|
22
|
+
symbol: str
|
|
23
|
+
poolMeta: str | None
|
|
24
|
+
underlyingTokens: list[str]
|
|
25
|
+
rewardTokens: list[str] | None
|
|
26
|
+
tvlUsd: float
|
|
27
|
+
apy: float
|
|
28
|
+
apyBase: float
|
|
29
|
+
apyReward: float | None
|
|
30
|
+
il7d: float | None
|
|
31
|
+
apyBase7d: float | None
|
|
32
|
+
volumeUsd1d: float | None
|
|
33
|
+
volumeUsd7d: float | None
|
|
34
|
+
apyBaseInception: float | None
|
|
35
|
+
url: str
|
|
36
|
+
apyPct1D: float
|
|
37
|
+
apyPct7D: float
|
|
38
|
+
apyPct30D: float
|
|
39
|
+
apyMean30d: float
|
|
40
|
+
stablecoin: bool
|
|
41
|
+
ilRisk: str
|
|
42
|
+
exposure: str
|
|
43
|
+
count: int
|
|
44
|
+
apyMeanExpanding: float
|
|
45
|
+
apyStdExpanding: float
|
|
46
|
+
mu: float
|
|
47
|
+
sigma: float
|
|
48
|
+
outlier: bool
|
|
49
|
+
project_factorized: int
|
|
50
|
+
chain_factorized: int
|
|
51
|
+
predictions: PoolPredictions
|
|
52
|
+
pool_old: str
|
|
53
|
+
pool_old_addr: str
|
|
54
|
+
pool_old_chain: str
|
|
55
|
+
apy_pct: float
|
|
56
|
+
kind: str
|
|
57
|
+
source: str
|
|
58
|
+
underlying_apy_pct: float | None
|
|
59
|
+
combined_apy_pct: float
|
|
60
|
+
id: str
|
|
61
|
+
address: str
|
|
62
|
+
network: str
|
|
63
|
+
chain_code: str
|
|
31
64
|
|
|
32
65
|
|
|
33
66
|
class PoolList(TypedDict):
|
|
34
|
-
"""Pool list response structure"""
|
|
35
|
-
|
|
36
67
|
pools: Required[list[PoolData]]
|
|
37
|
-
total: NotRequired[int | None]
|
|
38
68
|
|
|
39
69
|
|
|
40
|
-
class
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
70
|
+
class LlamaMatchesResponse(TypedDict):
|
|
71
|
+
matches: Required[list[PoolData]]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _normalize_pool(raw: dict[str, Any]) -> dict[str, Any]:
|
|
75
|
+
out = dict(raw)
|
|
76
|
+
pool_id_val = out.get("pool")
|
|
77
|
+
if pool_id_val is not None:
|
|
78
|
+
if "id" not in out:
|
|
79
|
+
out["id"] = pool_id_val
|
|
80
|
+
if "token_id" not in out:
|
|
81
|
+
out["token_id"] = pool_id_val
|
|
82
|
+
if "pool_id" not in out:
|
|
83
|
+
out["pool_id"] = pool_id_val
|
|
84
|
+
if "address" not in out and "pool_old_addr" in out:
|
|
85
|
+
out["address"] = out["pool_old_addr"]
|
|
86
|
+
chain_val = out.get("pool_old_chain") or out.get("chain")
|
|
87
|
+
if chain_val is not None:
|
|
88
|
+
chain_lower = (
|
|
89
|
+
chain_val.lower() if isinstance(chain_val, str) else str(chain_val)
|
|
90
|
+
)
|
|
91
|
+
if "network" not in out:
|
|
92
|
+
out["network"] = chain_lower
|
|
93
|
+
if "chain_code" not in out:
|
|
94
|
+
out["chain_code"] = chain_lower
|
|
95
|
+
return out
|
|
49
96
|
|
|
50
97
|
|
|
51
98
|
class PoolClient(WayfinderClient):
|
|
52
|
-
|
|
99
|
+
def __init__(self):
|
|
100
|
+
super().__init__()
|
|
101
|
+
self.api_base_url = get_api_base_url()
|
|
53
102
|
|
|
54
|
-
def
|
|
55
|
-
|
|
56
|
-
self.api_base_url = f"{get_api_base_url()}"
|
|
57
|
-
self._auth_client: AuthClient | None = AuthClient(api_key=api_key)
|
|
103
|
+
def _pools_url(self) -> str:
|
|
104
|
+
return f"{self.api_base_url}/v1/blockchain/pools/"
|
|
58
105
|
|
|
59
|
-
async def get_pools(
|
|
60
|
-
|
|
61
|
-
|
|
106
|
+
async def get_pools(
|
|
107
|
+
self,
|
|
108
|
+
*,
|
|
109
|
+
chain_id: int | None = None,
|
|
110
|
+
project: str | None = None,
|
|
111
|
+
) -> LlamaMatchesResponse:
|
|
112
|
+
url = self._pools_url()
|
|
113
|
+
params: dict[str, Any] = {}
|
|
114
|
+
if chain_id is not None:
|
|
115
|
+
params["chain_id"] = chain_id
|
|
116
|
+
if project is not None:
|
|
117
|
+
params["project"] = project
|
|
118
|
+
response = await self._request("GET", url, params=params, headers={})
|
|
62
119
|
response.raise_for_status()
|
|
63
120
|
data = response.json()
|
|
64
|
-
|
|
121
|
+
if isinstance(data, list):
|
|
122
|
+
data = [_normalize_pool(p) for p in data]
|
|
123
|
+
return {"matches": data}
|
|
124
|
+
inner = data.get("data", data)
|
|
125
|
+
if isinstance(inner, list):
|
|
126
|
+
return {"matches": [_normalize_pool(p) for p in inner]}
|
|
127
|
+
return {"matches": inner.get("matches", [])}
|
|
65
128
|
|
|
66
129
|
async def get_pools_by_ids(
|
|
67
130
|
self,
|
|
68
131
|
*,
|
|
69
|
-
pool_ids: str,
|
|
132
|
+
pool_ids: list[str] | str,
|
|
70
133
|
) -> PoolList:
|
|
71
|
-
url =
|
|
72
|
-
|
|
73
|
-
|
|
134
|
+
url = self._pools_url()
|
|
135
|
+
ids = (
|
|
136
|
+
pool_ids
|
|
137
|
+
if isinstance(pool_ids, list)
|
|
138
|
+
else [s.strip() for s in str(pool_ids).split(",") if s.strip()]
|
|
139
|
+
)
|
|
140
|
+
body: dict[str, Any] = {"pool_ids": ids}
|
|
141
|
+
response = await self._request("POST", url, json=body, headers={})
|
|
74
142
|
response.raise_for_status()
|
|
75
143
|
data = response.json()
|
|
76
|
-
|
|
144
|
+
if isinstance(data, list):
|
|
145
|
+
data = [_normalize_pool(p) for p in data]
|
|
146
|
+
return {"pools": data}
|
|
147
|
+
inner = data.get("data", data)
|
|
148
|
+
if isinstance(inner, list):
|
|
149
|
+
return {"pools": [_normalize_pool(p) for p in inner]}
|
|
150
|
+
return {"pools": inner.get("pools", [])}
|
|
@@ -7,83 +7,138 @@ from __future__ import annotations
|
|
|
7
7
|
|
|
8
8
|
from typing import NotRequired, Required, TypedDict
|
|
9
9
|
|
|
10
|
-
from wayfinder_paths.core.clients.AuthClient import AuthClient
|
|
11
10
|
from wayfinder_paths.core.clients.WayfinderClient import WayfinderClient
|
|
12
11
|
from wayfinder_paths.core.config import get_api_base_url
|
|
13
12
|
|
|
14
13
|
|
|
14
|
+
class TokenLinks(TypedDict):
|
|
15
|
+
"""Token links structure"""
|
|
16
|
+
|
|
17
|
+
github: NotRequired[list[str]]
|
|
18
|
+
reddit: NotRequired[str]
|
|
19
|
+
discord: NotRequired[str]
|
|
20
|
+
twitter: NotRequired[str]
|
|
21
|
+
homepage: NotRequired[list[str]]
|
|
22
|
+
telegram: NotRequired[str]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ChainAddress(TypedDict):
|
|
26
|
+
"""Chain address structure"""
|
|
27
|
+
|
|
28
|
+
address: Required[str]
|
|
29
|
+
token_id: Required[str]
|
|
30
|
+
is_contract: NotRequired[bool]
|
|
31
|
+
chain_id: NotRequired[int]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ChainInfo(TypedDict):
|
|
35
|
+
"""Chain information structure"""
|
|
36
|
+
|
|
37
|
+
id: Required[int]
|
|
38
|
+
name: Required[str]
|
|
39
|
+
code: Required[str]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class TokenMetadata(TypedDict):
|
|
43
|
+
"""Token metadata structure"""
|
|
44
|
+
|
|
45
|
+
query_processed: NotRequired[str]
|
|
46
|
+
query_type: NotRequired[str]
|
|
47
|
+
has_addresses: NotRequired[bool]
|
|
48
|
+
address_count: NotRequired[int]
|
|
49
|
+
has_price_data: NotRequired[bool]
|
|
50
|
+
|
|
51
|
+
|
|
15
52
|
class TokenDetails(TypedDict):
|
|
16
53
|
"""Token details response structure"""
|
|
17
54
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
symbol: Required[str]
|
|
55
|
+
asset_id: NotRequired[str]
|
|
56
|
+
token_ids: NotRequired[list[str]]
|
|
21
57
|
name: Required[str]
|
|
58
|
+
symbol: Required[str]
|
|
22
59
|
decimals: Required[int]
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
60
|
+
description: NotRequired[str]
|
|
61
|
+
links: NotRequired[TokenLinks]
|
|
62
|
+
categories: NotRequired[list[str]]
|
|
63
|
+
current_price: NotRequired[float]
|
|
64
|
+
market_cap: NotRequired[float]
|
|
65
|
+
total_volume_usd_24h: NotRequired[float]
|
|
66
|
+
price_change_24h: NotRequired[float]
|
|
67
|
+
price_change_7d: NotRequired[float]
|
|
68
|
+
price_change_30d: NotRequired[float]
|
|
69
|
+
price_change_1y: NotRequired[float]
|
|
70
|
+
addresses: NotRequired[dict[str, str]]
|
|
71
|
+
chain_addresses: NotRequired[dict[str, ChainAddress]]
|
|
72
|
+
chain_ids: NotRequired[dict[str, int]]
|
|
73
|
+
id: NotRequired[int]
|
|
74
|
+
token_id: Required[str]
|
|
75
|
+
address: Required[str]
|
|
76
|
+
chain: NotRequired[ChainInfo]
|
|
77
|
+
query: NotRequired[str]
|
|
78
|
+
query_type: NotRequired[str]
|
|
79
|
+
metadata: NotRequired[TokenMetadata]
|
|
27
80
|
image_url: NotRequired[str | None]
|
|
28
|
-
coingecko_id: NotRequired[str | None]
|
|
29
81
|
|
|
30
82
|
|
|
31
83
|
class GasToken(TypedDict):
|
|
32
84
|
"""Gas token response structure"""
|
|
33
85
|
|
|
34
86
|
id: Required[str]
|
|
35
|
-
|
|
36
|
-
|
|
87
|
+
coingecko_id: NotRequired[str]
|
|
88
|
+
token_id: Required[str]
|
|
37
89
|
name: Required[str]
|
|
90
|
+
symbol: Required[str]
|
|
91
|
+
address: Required[str]
|
|
38
92
|
decimals: Required[int]
|
|
39
|
-
|
|
40
|
-
chain_code: Required[str]
|
|
41
|
-
price_usd: NotRequired[float]
|
|
93
|
+
chain: NotRequired[ChainInfo]
|
|
42
94
|
|
|
43
95
|
|
|
44
96
|
class TokenClient(WayfinderClient):
|
|
45
97
|
"""Adapter for token-related operations"""
|
|
46
98
|
|
|
47
|
-
def __init__(self
|
|
48
|
-
super().__init__(
|
|
49
|
-
self.api_base_url = f"{
|
|
50
|
-
self._auth_client: AuthClient | None = AuthClient(api_key=api_key)
|
|
51
|
-
|
|
52
|
-
# ============== Public (No-Auth) Endpoints ==============
|
|
99
|
+
def __init__(self):
|
|
100
|
+
super().__init__()
|
|
101
|
+
self.api_base_url = f"{get_api_base_url()}/v1/blockchain/tokens"
|
|
53
102
|
|
|
54
103
|
async def get_token_details(
|
|
55
|
-
self,
|
|
104
|
+
self, query: str, market_data: bool = False, chain_id: int | None = None
|
|
56
105
|
) -> TokenDetails:
|
|
57
106
|
"""
|
|
58
|
-
Get token data including price from the token-details endpoint
|
|
107
|
+
Get token data including price from the token-details endpoint.
|
|
59
108
|
|
|
60
109
|
Args:
|
|
61
|
-
|
|
110
|
+
query: Token identifier, address, or symbol to query
|
|
111
|
+
market_data: Whether to include market data (default: True)
|
|
112
|
+
chain_id: Optional chain ID
|
|
62
113
|
|
|
63
114
|
Returns:
|
|
64
115
|
Full token data including price information
|
|
65
116
|
"""
|
|
66
|
-
url = f"{
|
|
117
|
+
url = f"{self.api_base_url}/detail/"
|
|
67
118
|
params = {
|
|
68
|
-
"query":
|
|
69
|
-
"
|
|
70
|
-
"force_refresh": str(force_refresh),
|
|
119
|
+
"query": query,
|
|
120
|
+
"market_data": market_data,
|
|
71
121
|
}
|
|
72
|
-
|
|
73
|
-
|
|
122
|
+
if chain_id is not None:
|
|
123
|
+
params["chain_id"] = chain_id
|
|
124
|
+
response = await self._authed_request("GET", url, params=params)
|
|
74
125
|
response.raise_for_status()
|
|
75
126
|
data = response.json()
|
|
76
127
|
return data.get("data", data)
|
|
77
128
|
|
|
78
|
-
async def get_gas_token(self,
|
|
129
|
+
async def get_gas_token(self, query: str) -> GasToken:
|
|
79
130
|
"""
|
|
80
|
-
Fetch the native gas token for a given chain code
|
|
81
|
-
|
|
131
|
+
Fetch the native gas token for a given chain code or query.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
query: Chain code or query string
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
Gas token information including chain details
|
|
82
138
|
"""
|
|
83
|
-
url = f"{
|
|
84
|
-
params = {"
|
|
85
|
-
|
|
86
|
-
response = await self._request("GET", url, params=params, headers={})
|
|
139
|
+
url = f"{self.api_base_url}/gas/"
|
|
140
|
+
params = {"query": query}
|
|
141
|
+
response = await self._authed_request("GET", url, params=params)
|
|
87
142
|
response.raise_for_status()
|
|
88
143
|
data = response.json()
|
|
89
144
|
return data.get("data", data)
|
|
@@ -7,80 +7,50 @@ from __future__ import annotations
|
|
|
7
7
|
|
|
8
8
|
from typing import NotRequired, Required, TypedDict
|
|
9
9
|
|
|
10
|
-
from wayfinder_paths.core.clients.AuthClient import AuthClient
|
|
11
10
|
from wayfinder_paths.core.clients.WayfinderClient import WayfinderClient
|
|
12
11
|
from wayfinder_paths.core.config import get_api_base_url
|
|
13
12
|
|
|
14
13
|
|
|
15
|
-
class
|
|
16
|
-
"""
|
|
14
|
+
class AddressBalance(TypedDict):
|
|
15
|
+
"""Balance response structure for address/query lookups."""
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
wallet_address: Required[str]
|
|
20
|
-
balance: Required[str]
|
|
21
|
-
balance_human: NotRequired[float | None]
|
|
22
|
-
usd_value: NotRequired[float | None]
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class PoolBalance(TypedDict):
|
|
26
|
-
"""Pool balance response structure"""
|
|
27
|
-
|
|
28
|
-
pool_address: Required[str]
|
|
29
|
-
chain_id: Required[int]
|
|
30
|
-
user_address: Required[str]
|
|
31
|
-
balance: Required[str]
|
|
17
|
+
balance: Required[int]
|
|
32
18
|
balance_human: NotRequired[float | None]
|
|
33
19
|
usd_value: NotRequired[float | None]
|
|
20
|
+
address: NotRequired[str]
|
|
21
|
+
token_id: NotRequired[str | None]
|
|
22
|
+
wallet_address: NotRequired[str]
|
|
23
|
+
chain_id: NotRequired[int]
|
|
34
24
|
|
|
35
25
|
|
|
36
26
|
class WalletClient(WayfinderClient):
|
|
37
|
-
def __init__(self
|
|
38
|
-
super().__init__(
|
|
27
|
+
def __init__(self):
|
|
28
|
+
super().__init__()
|
|
39
29
|
self.api_base_url = get_api_base_url()
|
|
40
|
-
self._auth_client = AuthClient(api_key=api_key)
|
|
41
30
|
|
|
42
|
-
async def
|
|
31
|
+
async def get_token_balance_for_address(
|
|
43
32
|
self,
|
|
44
33
|
*,
|
|
45
|
-
token_id: str,
|
|
46
34
|
wallet_address: str,
|
|
47
|
-
|
|
48
|
-
|
|
35
|
+
query: str,
|
|
36
|
+
chain_id: int | None = None,
|
|
37
|
+
) -> AddressBalance:
|
|
49
38
|
"""
|
|
50
|
-
Fetch a
|
|
39
|
+
Fetch a balance for a wallet address + chain + query.
|
|
51
40
|
|
|
52
|
-
|
|
41
|
+
Args:
|
|
42
|
+
wallet_address: Wallet address
|
|
43
|
+
query: Token address, pool address, or equivalent identifier
|
|
44
|
+
chain_id: Chain ID (required)
|
|
53
45
|
"""
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"token_id": token_id,
|
|
57
|
-
"wallet_address": wallet_address,
|
|
58
|
-
"human_readable": human_readable,
|
|
59
|
-
}
|
|
60
|
-
response = await self._authed_request("POST", url, json=payload)
|
|
61
|
-
data = response.json()
|
|
62
|
-
return data.get("data", data)
|
|
46
|
+
if chain_id is None:
|
|
47
|
+
raise ValueError("chain_id is required")
|
|
63
48
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
pool_address: str,
|
|
68
|
-
chain_id: int,
|
|
69
|
-
user_address: str,
|
|
70
|
-
human_readable: bool = True,
|
|
71
|
-
) -> PoolBalance:
|
|
72
|
-
"""
|
|
73
|
-
Fetch a wallet's LP/share balance for a given pool address and chain.
|
|
74
|
-
|
|
75
|
-
Mirrors POST /api/v1/public/balances/pool/
|
|
76
|
-
"""
|
|
77
|
-
url = f"{self.api_base_url}/public/balances/pool/"
|
|
78
|
-
payload = {
|
|
79
|
-
"pool_address": pool_address,
|
|
49
|
+
url = f"{self.api_base_url}/v1/blockchain/balances/address/"
|
|
50
|
+
params = {
|
|
51
|
+
"wallet_address": wallet_address,
|
|
80
52
|
"chain_id": chain_id,
|
|
81
|
-
"
|
|
82
|
-
"human_readable": human_readable,
|
|
53
|
+
"query": query,
|
|
83
54
|
}
|
|
84
|
-
response = await self._authed_request("
|
|
85
|
-
|
|
86
|
-
return data.get("data", data)
|
|
55
|
+
response = await self._authed_request("GET", url, params=params)
|
|
56
|
+
return response.json()
|