defillama-sdk 0.1.0__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.
@@ -0,0 +1,242 @@
1
+ """Fees module implementation."""
2
+
3
+ from typing import Optional
4
+ from urllib.parse import quote
5
+
6
+ from ..client import BaseClient
7
+ from ..types.fees import (
8
+ ChartBreakdownDataPoint,
9
+ ChartDataPoint,
10
+ FeesChartOptions,
11
+ FeesMetricsByProtocolResponse,
12
+ FeesMetricsResponse,
13
+ FeesOverviewOptions,
14
+ FeesOverviewResponse,
15
+ FeesSummaryOptions,
16
+ FeesSummaryResponse,
17
+ )
18
+
19
+
20
+ def _data_type_value(value: Optional[object]) -> Optional[str]:
21
+ if value is None:
22
+ return None
23
+ if hasattr(value, "value"):
24
+ return str(getattr(value, "value"))
25
+ return str(value)
26
+
27
+
28
+ class FeesModule:
29
+ """Access fees and revenue data from DefiLlama."""
30
+
31
+ def __init__(self, client: BaseClient) -> None:
32
+ self._client = client
33
+
34
+ def getOverview(self, options: Optional[FeesOverviewOptions] = None) -> FeesOverviewResponse:
35
+ """Get fees overview across all protocols."""
36
+
37
+ params = {}
38
+ if options:
39
+ if options.get("excludeTotalDataChart") is not None:
40
+ params["excludeTotalDataChart"] = options.get("excludeTotalDataChart")
41
+ if options.get("excludeTotalDataChartBreakdown") is not None:
42
+ params["excludeTotalDataChartBreakdown"] = options.get(
43
+ "excludeTotalDataChartBreakdown"
44
+ )
45
+ data_type = _data_type_value(options.get("dataType"))
46
+ if data_type:
47
+ params["dataType"] = data_type
48
+ return self._client.get(
49
+ "/overview/fees",
50
+ params=params or None,
51
+ )
52
+
53
+ def getOverviewByChain(
54
+ self, chain: str, options: Optional[FeesOverviewOptions] = None
55
+ ) -> FeesOverviewResponse:
56
+ """Get fees overview for a chain."""
57
+
58
+ params = {}
59
+ if options:
60
+ if options.get("excludeTotalDataChart") is not None:
61
+ params["excludeTotalDataChart"] = options.get("excludeTotalDataChart")
62
+ if options.get("excludeTotalDataChartBreakdown") is not None:
63
+ params["excludeTotalDataChartBreakdown"] = options.get(
64
+ "excludeTotalDataChartBreakdown"
65
+ )
66
+ data_type = _data_type_value(options.get("dataType"))
67
+ if data_type:
68
+ params["dataType"] = data_type
69
+ return self._client.get(
70
+ f"/overview/fees/{quote(chain)}",
71
+ params=params or None,
72
+ )
73
+
74
+ def getSummary(
75
+ self, protocol: str, options: Optional[FeesSummaryOptions] = None
76
+ ) -> FeesSummaryResponse:
77
+ """Get fees summary for a protocol."""
78
+
79
+ params = {}
80
+ data_type = _data_type_value(options.get("dataType") if options else None)
81
+ if data_type:
82
+ params["dataType"] = data_type
83
+ return self._client.get(
84
+ f"/summary/fees/{quote(protocol)}",
85
+ params=params or None,
86
+ )
87
+
88
+ def getChart(self, options: Optional[FeesChartOptions] = None) -> list[ChartDataPoint]:
89
+ """Get historical fees chart."""
90
+
91
+ params = {}
92
+ data_type = _data_type_value(options.get("dataType") if options else None)
93
+ if data_type:
94
+ params["dataType"] = data_type
95
+ return self._client.get(
96
+ "/chart/fees",
97
+ base="v2",
98
+ requires_auth=True,
99
+ params=params or None,
100
+ )
101
+
102
+ def getChartByChain(
103
+ self, chain: str, options: Optional[FeesChartOptions] = None
104
+ ) -> list[ChartDataPoint]:
105
+ """Get historical fees chart for a chain."""
106
+
107
+ params = {}
108
+ data_type = _data_type_value(options.get("dataType") if options else None)
109
+ if data_type:
110
+ params["dataType"] = data_type
111
+ return self._client.get(
112
+ f"/chart/fees/chain/{quote(chain)}",
113
+ base="v2",
114
+ requires_auth=True,
115
+ params=params or None,
116
+ )
117
+
118
+ def getChartByProtocol(
119
+ self, protocol: str, options: Optional[FeesChartOptions] = None
120
+ ) -> list[ChartDataPoint]:
121
+ """Get historical fees chart for a protocol."""
122
+
123
+ params = {}
124
+ data_type = _data_type_value(options.get("dataType") if options else None)
125
+ if data_type:
126
+ params["dataType"] = data_type
127
+ return self._client.get(
128
+ f"/chart/fees/protocol/{quote(protocol)}",
129
+ base="v2",
130
+ requires_auth=True,
131
+ params=params or None,
132
+ )
133
+
134
+ def getChartByProtocolChainBreakdown(
135
+ self, protocol: str, options: Optional[FeesChartOptions] = None
136
+ ) -> list[ChartBreakdownDataPoint]:
137
+ """Get fees chart with protocol chain breakdown."""
138
+
139
+ params = {}
140
+ data_type = _data_type_value(options.get("dataType") if options else None)
141
+ if data_type:
142
+ params["dataType"] = data_type
143
+ return self._client.get(
144
+ f"/chart/fees/protocol/{quote(protocol)}/chain-breakdown",
145
+ base="v2",
146
+ requires_auth=True,
147
+ params=params or None,
148
+ )
149
+
150
+ def getChartByProtocolVersionBreakdown(
151
+ self, protocol: str, options: Optional[FeesChartOptions] = None
152
+ ) -> list[ChartBreakdownDataPoint]:
153
+ """Get fees chart with protocol version breakdown."""
154
+
155
+ params = {}
156
+ data_type = _data_type_value(options.get("dataType") if options else None)
157
+ if data_type:
158
+ params["dataType"] = data_type
159
+ return self._client.get(
160
+ f"/chart/fees/protocol/{quote(protocol)}/version-breakdown",
161
+ base="v2",
162
+ requires_auth=True,
163
+ params=params or None,
164
+ )
165
+
166
+ def getChartByChainProtocolBreakdown(
167
+ self, chain: str, options: Optional[FeesChartOptions] = None
168
+ ) -> list[ChartBreakdownDataPoint]:
169
+ """Get fees chart with chain protocol breakdown."""
170
+
171
+ params = {}
172
+ data_type = _data_type_value(options.get("dataType") if options else None)
173
+ if data_type:
174
+ params["dataType"] = data_type
175
+ return self._client.get(
176
+ f"/chart/fees/chain/{quote(chain)}/protocol-breakdown",
177
+ base="v2",
178
+ requires_auth=True,
179
+ params=params or None,
180
+ )
181
+
182
+ def getChartChainBreakdown(
183
+ self, options: Optional[FeesChartOptions] = None
184
+ ) -> list[ChartBreakdownDataPoint]:
185
+ """Get fees chart with chain breakdown across protocols."""
186
+
187
+ params = {}
188
+ data_type = _data_type_value(options.get("dataType") if options else None)
189
+ if data_type:
190
+ params["dataType"] = data_type
191
+ return self._client.get(
192
+ "/chart/fees/chain-breakdown",
193
+ base="v2",
194
+ requires_auth=True,
195
+ params=params or None,
196
+ )
197
+
198
+ def getMetrics(self, options: Optional[FeesChartOptions] = None) -> FeesMetricsResponse:
199
+ """Get fee metrics across protocols."""
200
+
201
+ params = {}
202
+ data_type = _data_type_value(options.get("dataType") if options else None)
203
+ if data_type:
204
+ params["dataType"] = data_type
205
+ return self._client.get(
206
+ "/metrics/fees",
207
+ base="v2",
208
+ requires_auth=True,
209
+ params=params or None,
210
+ )
211
+
212
+ def getMetricsByChain(
213
+ self, chain: str, options: Optional[FeesChartOptions] = None
214
+ ) -> FeesMetricsResponse:
215
+ """Get fee metrics for a chain."""
216
+
217
+ params = {}
218
+ data_type = _data_type_value(options.get("dataType") if options else None)
219
+ if data_type:
220
+ params["dataType"] = data_type
221
+ return self._client.get(
222
+ f"/metrics/fees/chain/{quote(chain)}",
223
+ base="v2",
224
+ requires_auth=True,
225
+ params=params or None,
226
+ )
227
+
228
+ def getMetricsByProtocol(
229
+ self, protocol: str, options: Optional[FeesChartOptions] = None
230
+ ) -> FeesMetricsByProtocolResponse:
231
+ """Get fee metrics for a protocol."""
232
+
233
+ params = {}
234
+ data_type = _data_type_value(options.get("dataType") if options else None)
235
+ if data_type:
236
+ params["dataType"] = data_type
237
+ return self._client.get(
238
+ f"/metrics/fees/protocol/{quote(protocol)}",
239
+ base="v2",
240
+ requires_auth=True,
241
+ params=params or None,
242
+ )
@@ -0,0 +1,122 @@
1
+ """Prices module implementation."""
2
+
3
+ import json
4
+ from typing import Dict, List, Optional
5
+ from urllib.parse import quote
6
+
7
+ from ..client import BaseClient
8
+ from ..types.prices import (
9
+ BatchHistoricalResponse,
10
+ BlockInfo,
11
+ ChartOptions,
12
+ ChartResponse,
13
+ CoinPricesResponse,
14
+ FirstPriceResponse,
15
+ PercentageOptions,
16
+ PercentageResponse,
17
+ )
18
+
19
+
20
+ class PricesModule:
21
+ """Access token price data from DefiLlama."""
22
+
23
+ def __init__(self, client: BaseClient) -> None:
24
+ self._client = client
25
+
26
+ def getCurrentPrices(
27
+ self, coins: List[str], searchWidth: Optional[str] = None
28
+ ) -> CoinPricesResponse:
29
+ """Get current prices for multiple tokens."""
30
+
31
+ coins_param = ",".join(coins)
32
+ params = {"searchWidth": searchWidth} if searchWidth else None
33
+ return self._client.get(
34
+ f"/prices/current/{coins_param}",
35
+ base="coins",
36
+ params=params,
37
+ )
38
+
39
+ def getHistoricalPrices(
40
+ self, timestamp: int, coins: List[str], searchWidth: Optional[str] = None
41
+ ) -> CoinPricesResponse:
42
+ """Get historical prices at a specific timestamp."""
43
+
44
+ coins_param = ",".join(coins)
45
+ params = {"searchWidth": searchWidth} if searchWidth else None
46
+ return self._client.get(
47
+ f"/prices/historical/{timestamp}/{coins_param}",
48
+ base="coins",
49
+ params=params,
50
+ )
51
+
52
+ def getBatchHistoricalPrices(
53
+ self, coins: Dict[str, List[int]], searchWidth: Optional[str] = None
54
+ ) -> BatchHistoricalResponse:
55
+ """Get multiple historical price points in one request."""
56
+
57
+ params = {
58
+ "coins": json.dumps(coins),
59
+ "searchWidth": searchWidth,
60
+ }
61
+ return self._client.get(
62
+ "/batchHistorical",
63
+ base="coins",
64
+ params=params,
65
+ )
66
+
67
+ def getChart(
68
+ self, coins: List[str], options: Optional[ChartOptions] = None
69
+ ) -> ChartResponse:
70
+ """Get price chart data at regular intervals."""
71
+
72
+ coins_param = ",".join(coins)
73
+ params = None
74
+ if options:
75
+ params = {
76
+ "start": options.get("start"),
77
+ "end": options.get("end"),
78
+ "span": options.get("span"),
79
+ "period": options.get("period"),
80
+ "searchWidth": options.get("searchWidth"),
81
+ }
82
+ return self._client.get(
83
+ f"/chart/{coins_param}",
84
+ base="coins",
85
+ params=params,
86
+ )
87
+
88
+ def getPercentageChange(
89
+ self, coins: List[str], options: Optional[PercentageOptions] = None
90
+ ) -> PercentageResponse:
91
+ """Get percentage price change over a period."""
92
+
93
+ coins_param = ",".join(coins)
94
+ params = None
95
+ if options:
96
+ params = {
97
+ "timestamp": options.get("timestamp"),
98
+ "lookForward": options.get("lookForward"),
99
+ "period": options.get("period"),
100
+ }
101
+ return self._client.get(
102
+ f"/percentage/{coins_param}",
103
+ base="coins",
104
+ params=params,
105
+ )
106
+
107
+ def getFirstPrices(self, coins: List[str]) -> FirstPriceResponse:
108
+ """Get the earliest recorded price for tokens."""
109
+
110
+ coins_param = ",".join(coins)
111
+ return self._client.get(
112
+ f"/prices/first/{coins_param}",
113
+ base="coins",
114
+ )
115
+
116
+ def getBlockAtTimestamp(self, chain: str, timestamp: int) -> BlockInfo:
117
+ """Get the closest block to a given timestamp."""
118
+
119
+ return self._client.get(
120
+ f"/block/{quote(chain)}/{timestamp}",
121
+ base="coins",
122
+ )
@@ -0,0 +1,76 @@
1
+ """Stablecoins module implementation."""
2
+
3
+ from typing import List, Optional
4
+ from urllib.parse import quote
5
+
6
+ from ..client import BaseClient
7
+ from ..types.stablecoins import (
8
+ StablecoinChainDataPoint,
9
+ StablecoinChainMcap,
10
+ StablecoinChartDataPoint,
11
+ StablecoinDetails,
12
+ StablecoinDominanceDataPoint,
13
+ StablecoinPricePoint,
14
+ StablecoinsResponse,
15
+ )
16
+
17
+
18
+ class StablecoinsModule:
19
+ """Access stablecoin data from DefiLlama."""
20
+
21
+ def __init__(self, client: BaseClient) -> None:
22
+ self._client = client
23
+
24
+ def getStablecoins(self, includePrices: Optional[bool] = None) -> StablecoinsResponse:
25
+ """Get all stablecoins with current market caps."""
26
+
27
+ params = {"includePrices": includePrices} if includePrices is not None else None
28
+ return self._client.get(
29
+ "/stablecoins",
30
+ base="stablecoins",
31
+ params=params,
32
+ )
33
+
34
+ def getAllCharts(self) -> List[StablecoinChartDataPoint]:
35
+ """Get historical market cap data for all stablecoins."""
36
+
37
+ return self._client.get("/stablecoincharts/all", base="stablecoins")
38
+
39
+ def getChartsByChain(self, chain: str) -> List[StablecoinChainDataPoint]:
40
+ """Get historical market cap data for stablecoins on a chain."""
41
+
42
+ return self._client.get(
43
+ f"/stablecoincharts/{quote(chain)}",
44
+ base="stablecoins",
45
+ )
46
+
47
+ def getStablecoin(self, asset: str) -> StablecoinDetails:
48
+ """Get detailed information about a stablecoin."""
49
+
50
+ return self._client.get(
51
+ f"/stablecoin/{quote(asset)}",
52
+ base="stablecoins",
53
+ )
54
+
55
+ def getChains(self) -> List[StablecoinChainMcap]:
56
+ """Get stablecoin market cap for all chains."""
57
+
58
+ return self._client.get("/stablecoinchains", base="stablecoins")
59
+
60
+ def getPrices(self) -> List[StablecoinPricePoint]:
61
+ """Get historical prices for all stablecoins."""
62
+
63
+ return self._client.get("/stablecoinprices", base="stablecoins")
64
+
65
+ def getDominance(
66
+ self, chain: str, stablecoinId: Optional[int] = None
67
+ ) -> List[StablecoinDominanceDataPoint]:
68
+ """Get stablecoin dominance data for a chain."""
69
+
70
+ params = {"stablecoin": stablecoinId} if stablecoinId is not None else None
71
+ return self._client.get(
72
+ f"/stablecoindominance/{quote(chain)}",
73
+ requires_auth=True,
74
+ api_namespace="stablecoins",
75
+ params=params,
76
+ )
@@ -0,0 +1,84 @@
1
+ """TVL module implementation."""
2
+
3
+ from typing import List, Optional, Union
4
+ from urllib.parse import quote
5
+
6
+ from ..client import BaseClient
7
+ from ..types.tvl import (
8
+ Chain,
9
+ ChainAssetsResponse,
10
+ HistoricalChainTvl,
11
+ HistoricalChainsTvl,
12
+ Protocol,
13
+ ProtocolDetails,
14
+ ProtocolInflowsResponse,
15
+ TokenProtocolHolding,
16
+ )
17
+
18
+
19
+ class TvlModule:
20
+ """Access TVL data from DefiLlama."""
21
+
22
+ def __init__(self, client: BaseClient) -> None:
23
+ self._client = client
24
+
25
+ def getProtocols(self) -> List[Protocol]:
26
+ """Get all protocols with current TVL."""
27
+
28
+ return self._client.get("/protocols")
29
+
30
+ def getProtocol(self, protocol: str) -> ProtocolDetails:
31
+ """Get detailed protocol information with historical TVL."""
32
+
33
+ return self._client.get(f"/protocol/{quote(protocol)}")
34
+
35
+ def getTvl(self, protocol: str) -> float:
36
+ """Get current TVL for a protocol."""
37
+
38
+ return self._client.get(f"/tvl/{quote(protocol)}")
39
+
40
+ def getChains(self) -> List[Chain]:
41
+ """Get current TVL for all chains."""
42
+
43
+ return self._client.get("/v2/chains")
44
+
45
+ def getHistoricalChainTvl(
46
+ self, chain: Optional[str] = None
47
+ ) -> Union[List[HistoricalChainsTvl], List[HistoricalChainTvl]]:
48
+ """Get historical TVL data for all chains or a specific chain."""
49
+
50
+ if chain:
51
+ return self._client.get(f"/v2/historicalChainTvl/{quote(chain)}")
52
+ return self._client.get("/v2/historicalChainTvl")
53
+
54
+ def getTokenProtocols(self, symbol: str) -> List[TokenProtocolHolding]:
55
+ """Get protocols that hold a specific token."""
56
+
57
+ return self._client.get(
58
+ f"/tokenProtocols/{quote(symbol)}",
59
+ requires_auth=True,
60
+ )
61
+
62
+ def getInflows(
63
+ self,
64
+ protocol: str,
65
+ start_timestamp: int,
66
+ end_timestamp: int,
67
+ tokens_to_exclude: Optional[str] = None,
68
+ ) -> ProtocolInflowsResponse:
69
+ """Get token inflows/outflows for a protocol."""
70
+
71
+ params = {
72
+ "end": end_timestamp,
73
+ "tokensToExclude": tokens_to_exclude or "",
74
+ }
75
+ return self._client.get(
76
+ f"/inflows/{quote(protocol)}/{start_timestamp}",
77
+ requires_auth=True,
78
+ params=params,
79
+ )
80
+
81
+ def getChainAssets(self) -> ChainAssetsResponse:
82
+ """Get asset breakdown for all chains."""
83
+
84
+ return self._client.get("/chainAssets", requires_auth=True)
@@ -0,0 +1,116 @@
1
+ """Volumes module implementation."""
2
+
3
+ from typing import Optional
4
+ from urllib.parse import quote
5
+
6
+ from ..client import BaseClient
7
+ from ..types.volumes import (
8
+ DexOverviewOptions,
9
+ DexOverviewResponse,
10
+ DexSummaryOptions,
11
+ DexSummaryResponse,
12
+ DerivativesOverviewResponse,
13
+ DerivativesSummaryResponse,
14
+ OptionsOverviewOptions,
15
+ OptionsOverviewResponse,
16
+ OptionsSummaryResponse,
17
+ )
18
+
19
+
20
+ class VolumesModule:
21
+ """Access volume data from DefiLlama."""
22
+
23
+ def __init__(self, client: BaseClient) -> None:
24
+ self._client = client
25
+
26
+ def getDexOverview(
27
+ self, options: Optional[DexOverviewOptions] = None
28
+ ) -> DexOverviewResponse:
29
+ """Get overview of DEX volume data."""
30
+
31
+ params = {}
32
+ if options:
33
+ if options.get("excludeTotalDataChart") is not None:
34
+ params["excludeTotalDataChart"] = options.get("excludeTotalDataChart")
35
+ if options.get("excludeTotalDataChartBreakdown") is not None:
36
+ params["excludeTotalDataChartBreakdown"] = options.get(
37
+ "excludeTotalDataChartBreakdown"
38
+ )
39
+ if options.get("dataType"):
40
+ params["dataType"] = options.get("dataType")
41
+ return self._client.get(
42
+ "/overview/dexs",
43
+ params=params or None,
44
+ )
45
+
46
+ def getDexOverviewByChain(
47
+ self, chain: str, options: Optional[DexOverviewOptions] = None
48
+ ) -> DexOverviewResponse:
49
+ """Get DEX volume overview for a chain."""
50
+
51
+ params = {}
52
+ if options:
53
+ if options.get("excludeTotalDataChart") is not None:
54
+ params["excludeTotalDataChart"] = options.get("excludeTotalDataChart")
55
+ if options.get("excludeTotalDataChartBreakdown") is not None:
56
+ params["excludeTotalDataChartBreakdown"] = options.get(
57
+ "excludeTotalDataChartBreakdown"
58
+ )
59
+ return self._client.get(
60
+ f"/overview/dexs/{quote(chain)}",
61
+ params=params or None,
62
+ )
63
+
64
+ def getDexSummary(
65
+ self, protocol: str, options: Optional[DexSummaryOptions] = None
66
+ ) -> DexSummaryResponse:
67
+ """Get DEX volume summary for a protocol."""
68
+
69
+ params = {}
70
+ if options and options.get("dataType"):
71
+ params["dataType"] = options.get("dataType")
72
+ return self._client.get(
73
+ f"/summary/dexs/{quote(protocol)}",
74
+ params=params or None,
75
+ )
76
+
77
+ def getOptionsOverview(
78
+ self, options: Optional[OptionsOverviewOptions] = None
79
+ ) -> OptionsOverviewResponse:
80
+ """Get options volume overview."""
81
+
82
+ params = {}
83
+ if options:
84
+ if options.get("excludeTotalDataChart") is not None:
85
+ params["excludeTotalDataChart"] = options.get("excludeTotalDataChart")
86
+ if options.get("excludeTotalDataChartBreakdown") is not None:
87
+ params["excludeTotalDataChartBreakdown"] = options.get(
88
+ "excludeTotalDataChartBreakdown"
89
+ )
90
+ return self._client.get(
91
+ "/overview/options",
92
+ params=params or None,
93
+ )
94
+
95
+ def getOptionsOverviewByChain(self, chain: str) -> OptionsOverviewResponse:
96
+ """Get options volume for a chain."""
97
+
98
+ return self._client.get(f"/overview/options/{quote(chain)}")
99
+
100
+ def getOptionsSummary(self, protocol: str) -> OptionsSummaryResponse:
101
+ """Get options volume summary for a protocol."""
102
+
103
+ return self._client.get(f"/summary/options/{quote(protocol)}")
104
+
105
+ def getDerivativesOverview(self) -> DerivativesOverviewResponse:
106
+ """Get derivatives volume overview."""
107
+
108
+ return self._client.get("/overview/derivatives", requires_auth=True)
109
+
110
+ def getDerivativesSummary(self, protocol: str) -> DerivativesSummaryResponse:
111
+ """Get derivatives volume summary for a protocol."""
112
+
113
+ return self._client.get(
114
+ f"/summary/derivatives/{quote(protocol)}",
115
+ requires_auth=True,
116
+ )