defistream 1.0.0__py3-none-any.whl → 1.0.2__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.
defistream/__init__.py CHANGED
@@ -1,19 +1,22 @@
1
1
  """
2
2
  DeFiStream Python Client
3
3
 
4
- Official Python client for the DeFiStream API - access historical
5
- DeFi events from 45+ EVM networks.
4
+ Official Python client for the DeFiStream API.
6
5
 
7
6
  Example:
8
7
  >>> from defistream import DeFiStream
9
8
  >>> client = DeFiStream(api_key="dsk_...")
10
9
  >>>
11
- >>> # Builder pattern
12
- >>> query = client.erc20.transfers("USDT").network("ETH").start_block(24000000).end_block(24100000)
13
- >>> transfers = query.as_dict()
10
+ >>> # Builder pattern - returns pandas DataFrame
11
+ >>> df = (
12
+ ... client.erc20.transfers("USDT")
13
+ ... .network("ETH")
14
+ ... .block_range(21000000, 21010000)
15
+ ... .as_df()
16
+ ... )
14
17
  >>>
15
18
  >>> # Save to file
16
- >>> query.to_csv_file("transfers.csv")
19
+ >>> query.as_file("transfers.parquet")
17
20
  """
18
21
 
19
22
  from .client import AsyncDeFiStream, DeFiStream
@@ -32,20 +35,17 @@ from .models import (
32
35
  AAVELiquidationEvent,
33
36
  AAVERepayEvent,
34
37
  AAVEWithdrawEvent,
35
- ERC20ApprovalEvent,
36
38
  ERC20TransferEvent,
37
39
  EventBase,
38
40
  LidoDepositEvent,
39
41
  LidoWithdrawEvent,
40
42
  NativeTransferEvent,
41
43
  ResponseMetadata,
42
- UniswapBurnEvent,
43
- UniswapMintEvent,
44
44
  UniswapSwapEvent,
45
45
  )
46
46
  from .query import AsyncQueryBuilder, QueryBuilder
47
47
 
48
- __version__ = "0.1.0"
48
+ __version__ = "1.0.2"
49
49
 
50
50
  __all__ = [
51
51
  # Clients
@@ -66,7 +66,6 @@ __all__ = [
66
66
  "EventBase",
67
67
  "ResponseMetadata",
68
68
  "ERC20TransferEvent",
69
- "ERC20ApprovalEvent",
70
69
  "NativeTransferEvent",
71
70
  "AAVEDepositEvent",
72
71
  "AAVEWithdrawEvent",
@@ -74,8 +73,6 @@ __all__ = [
74
73
  "AAVERepayEvent",
75
74
  "AAVELiquidationEvent",
76
75
  "UniswapSwapEvent",
77
- "UniswapMintEvent",
78
- "UniswapBurnEvent",
79
76
  "LidoDepositEvent",
80
77
  "LidoWithdrawEvent",
81
78
  ]
defistream/protocols.py CHANGED
@@ -21,34 +21,25 @@ class ERC20Protocol:
21
21
  Start a query for ERC20 transfer events.
22
22
 
23
23
  Args:
24
- token: Optional token symbol (USDT, USDC, WETH, etc.)
24
+ token: Token symbol (USDT, USDC, WETH, etc.) or contract address
25
25
 
26
26
  Returns:
27
27
  QueryBuilder for chaining filters
28
28
 
29
29
  Example:
30
- query = client.erc20.transfers("USDT").network("ETH").start_block(24000000).end_block(24100000)
31
- df = query.as_pandas()
30
+ df = (
31
+ client.erc20.transfers("USDT")
32
+ .network("ETH")
33
+ .block_range(21000000, 21010000)
34
+ .as_df()
35
+ )
32
36
  """
33
37
  params = {"token": token} if token else {}
34
38
  return QueryBuilder(self._client, "/erc20/events/transfer", params)
35
39
 
36
- def approvals(self, token: str | None = None) -> QueryBuilder:
37
- """
38
- Start a query for ERC20 approval events.
39
-
40
- Args:
41
- token: Optional token symbol
42
-
43
- Returns:
44
- QueryBuilder for chaining filters
45
- """
46
- params = {"token": token} if token else {}
47
- return QueryBuilder(self._client, "/erc20/events/approval", params)
48
-
49
40
 
50
41
  class NativeTokenProtocol:
51
- """Native token (ETH, MATIC, BNB, etc.) events with builder pattern."""
42
+ """Native token (ETH, MATIC, etc.) events with builder pattern."""
52
43
 
53
44
  def __init__(self, client: "BaseClient"):
54
45
  self._client = client
@@ -61,8 +52,13 @@ class NativeTokenProtocol:
61
52
  QueryBuilder for chaining filters
62
53
 
63
54
  Example:
64
- query = client.native_token.transfers().network("ETH").start_block(24000000).end_block(24100000)
65
- transfers = query.min_amount(1.0).as_dict()
55
+ df = (
56
+ client.native_token.transfers()
57
+ .network("ETH")
58
+ .block_range(21000000, 21010000)
59
+ .min_amount(1.0)
60
+ .as_df()
61
+ )
66
62
  """
67
63
  return QueryBuilder(self._client, "/native_token/events/transfer")
68
64
 
@@ -89,6 +85,10 @@ class AAVEProtocol:
89
85
  """Start a query for AAVE repay events."""
90
86
  return QueryBuilder(self._client, "/aave/events/repay")
91
87
 
88
+ def flashloans(self) -> QueryBuilder:
89
+ """Start a query for AAVE flash loan events."""
90
+ return QueryBuilder(self._client, "/aave/events/flashloan")
91
+
92
92
  def liquidations(self) -> QueryBuilder:
93
93
  """Start a query for AAVE liquidation events."""
94
94
  return QueryBuilder(self._client, "/aave/events/liquidation")
@@ -110,16 +110,20 @@ class UniswapProtocol:
110
110
  Start a query for Uniswap V3 swap events.
111
111
 
112
112
  Args:
113
- symbol0: Optional first token symbol (e.g., WETH)
114
- symbol1: Optional second token symbol (e.g., USDC)
115
- fee: Optional fee tier (100, 500, 3000, 10000)
113
+ symbol0: First token symbol (e.g., WETH)
114
+ symbol1: Second token symbol (e.g., USDC)
115
+ fee: Fee tier (100, 500, 3000, 10000)
116
116
 
117
117
  Returns:
118
118
  QueryBuilder for chaining filters
119
119
 
120
120
  Example:
121
- query = client.uniswap.swaps("WETH", "USDC", 500).network("ETH").start_block(24000000).end_block(24100000)
122
- df = query.as_pandas()
121
+ df = (
122
+ client.uniswap.swaps("WETH", "USDC", 500)
123
+ .network("ETH")
124
+ .block_range(21000000, 21010000)
125
+ .as_df()
126
+ )
123
127
  """
124
128
  params: dict[str, Any] = {}
125
129
  if symbol0:
@@ -130,13 +134,13 @@ class UniswapProtocol:
130
134
  params["fee"] = fee
131
135
  return QueryBuilder(self._client, "/uniswap/events/swap", params)
132
136
 
133
- def mints(
137
+ def deposits(
134
138
  self,
135
139
  symbol0: str | None = None,
136
140
  symbol1: str | None = None,
137
141
  fee: int | None = None,
138
142
  ) -> QueryBuilder:
139
- """Start a query for Uniswap V3 mint (add liquidity) events."""
143
+ """Start a query for Uniswap V3 deposit (add liquidity) events."""
140
144
  params: dict[str, Any] = {}
141
145
  if symbol0:
142
146
  params["symbol0"] = symbol0
@@ -144,15 +148,15 @@ class UniswapProtocol:
144
148
  params["symbol1"] = symbol1
145
149
  if fee:
146
150
  params["fee"] = fee
147
- return QueryBuilder(self._client, "/uniswap/events/mint", params)
151
+ return QueryBuilder(self._client, "/uniswap/events/deposit", params)
148
152
 
149
- def burns(
153
+ def withdrawals(
150
154
  self,
151
155
  symbol0: str | None = None,
152
156
  symbol1: str | None = None,
153
157
  fee: int | None = None,
154
158
  ) -> QueryBuilder:
155
- """Start a query for Uniswap V3 burn (remove liquidity) events."""
159
+ """Start a query for Uniswap V3 withdrawal (remove liquidity) events."""
156
160
  params: dict[str, Any] = {}
157
161
  if symbol0:
158
162
  params["symbol0"] = symbol0
@@ -160,7 +164,23 @@ class UniswapProtocol:
160
164
  params["symbol1"] = symbol1
161
165
  if fee:
162
166
  params["fee"] = fee
163
- return QueryBuilder(self._client, "/uniswap/events/burn", params)
167
+ return QueryBuilder(self._client, "/uniswap/events/withdraw", params)
168
+
169
+ def collects(
170
+ self,
171
+ symbol0: str | None = None,
172
+ symbol1: str | None = None,
173
+ fee: int | None = None,
174
+ ) -> QueryBuilder:
175
+ """Start a query for Uniswap V3 collect (fee collection) events."""
176
+ params: dict[str, Any] = {}
177
+ if symbol0:
178
+ params["symbol0"] = symbol0
179
+ if symbol1:
180
+ params["symbol1"] = symbol1
181
+ if fee:
182
+ params["fee"] = fee
183
+ return QueryBuilder(self._client, "/uniswap/events/collect", params)
164
184
 
165
185
 
166
186
  class LidoProtocol:
@@ -169,17 +189,31 @@ class LidoProtocol:
169
189
  def __init__(self, client: "BaseClient"):
170
190
  self._client = client
171
191
 
192
+ # L1 ETH events
172
193
  def deposits(self) -> QueryBuilder:
173
- """Start a query for Lido stETH deposit events."""
194
+ """Start a query for Lido stETH deposit events (ETH L1 only)."""
174
195
  return QueryBuilder(self._client, "/lido/events/deposit")
175
196
 
176
- def withdrawals(self) -> QueryBuilder:
177
- """Start a query for Lido withdrawal events."""
178
- return QueryBuilder(self._client, "/lido/events/withdraw")
197
+ def withdrawal_requests(self) -> QueryBuilder:
198
+ """Start a query for Lido withdrawal request events (ETH L1 only)."""
199
+ return QueryBuilder(self._client, "/lido/events/withdrawal_request")
200
+
201
+ def withdrawals_claimed(self) -> QueryBuilder:
202
+ """Start a query for Lido claimed withdrawal events (ETH L1 only)."""
203
+ return QueryBuilder(self._client, "/lido/events/withdrawal_claimed")
204
+
205
+ # L2 events
206
+ def l2_deposits(self) -> QueryBuilder:
207
+ """Start a query for Lido L2 deposit events (L2 networks only)."""
208
+ return QueryBuilder(self._client, "/lido/events/l2_deposit")
209
+
210
+ def l2_withdrawal_requests(self) -> QueryBuilder:
211
+ """Start a query for Lido L2 withdrawal request events (L2 networks only)."""
212
+ return QueryBuilder(self._client, "/lido/events/l2_withdrawal_request")
179
213
 
180
214
 
181
215
  class StaderProtocol:
182
- """Stader EthX staking events with builder pattern."""
216
+ """Stader ETHx staking events with builder pattern (ETH only)."""
183
217
 
184
218
  def __init__(self, client: "BaseClient"):
185
219
  self._client = client
@@ -188,24 +222,36 @@ class StaderProtocol:
188
222
  """Start a query for Stader deposit events."""
189
223
  return QueryBuilder(self._client, "/stader/events/deposit")
190
224
 
225
+ def withdrawal_requests(self) -> QueryBuilder:
226
+ """Start a query for Stader withdrawal request events."""
227
+ return QueryBuilder(self._client, "/stader/events/withdrawal_request")
228
+
191
229
  def withdrawals(self) -> QueryBuilder:
192
230
  """Start a query for Stader withdrawal events."""
193
- return QueryBuilder(self._client, "/stader/events/withdraw")
231
+ return QueryBuilder(self._client, "/stader/events/withdrawal")
194
232
 
195
233
 
196
234
  class ThresholdProtocol:
197
- """Threshold tBTC events with builder pattern."""
235
+ """Threshold tBTC events with builder pattern (ETH only)."""
198
236
 
199
237
  def __init__(self, client: "BaseClient"):
200
238
  self._client = client
201
239
 
202
- def mints(self) -> QueryBuilder:
203
- """Start a query for tBTC mint events."""
204
- return QueryBuilder(self._client, "/threshold/events/mint")
240
+ def deposit_requests(self) -> QueryBuilder:
241
+ """Start a query for tBTC deposit request (reveal) events."""
242
+ return QueryBuilder(self._client, "/threshold/events/deposit_request")
205
243
 
206
- def burns(self) -> QueryBuilder:
207
- """Start a query for tBTC burn/redeem events."""
208
- return QueryBuilder(self._client, "/threshold/events/burn")
244
+ def deposits(self) -> QueryBuilder:
245
+ """Start a query for tBTC deposit (mint) events."""
246
+ return QueryBuilder(self._client, "/threshold/events/deposit")
247
+
248
+ def withdrawal_requests(self) -> QueryBuilder:
249
+ """Start a query for tBTC withdrawal request events."""
250
+ return QueryBuilder(self._client, "/threshold/events/withdrawal_request")
251
+
252
+ def withdrawals(self) -> QueryBuilder:
253
+ """Start a query for tBTC withdrawal (unmint) events."""
254
+ return QueryBuilder(self._client, "/threshold/events/withdrawal")
209
255
 
210
256
 
211
257
  # Async protocol implementations
@@ -220,11 +266,6 @@ class AsyncERC20Protocol:
220
266
  params = {"token": token} if token else {}
221
267
  return AsyncQueryBuilder(self._client, "/erc20/events/transfer", params)
222
268
 
223
- def approvals(self, token: str | None = None) -> AsyncQueryBuilder:
224
- """Start a query for ERC20 approval events."""
225
- params = {"token": token} if token else {}
226
- return AsyncQueryBuilder(self._client, "/erc20/events/approval", params)
227
-
228
269
 
229
270
  class AsyncNativeTokenProtocol:
230
271
  """Async native token events with builder pattern."""
@@ -259,6 +300,10 @@ class AsyncAAVEProtocol:
259
300
  """Start a query for AAVE repay events."""
260
301
  return AsyncQueryBuilder(self._client, "/aave/events/repay")
261
302
 
303
+ def flashloans(self) -> AsyncQueryBuilder:
304
+ """Start a query for AAVE flash loan events."""
305
+ return AsyncQueryBuilder(self._client, "/aave/events/flashloan")
306
+
262
307
  def liquidations(self) -> AsyncQueryBuilder:
263
308
  """Start a query for AAVE liquidation events."""
264
309
  return AsyncQueryBuilder(self._client, "/aave/events/liquidation")
@@ -286,13 +331,29 @@ class AsyncUniswapProtocol:
286
331
  params["fee"] = fee
287
332
  return AsyncQueryBuilder(self._client, "/uniswap/events/swap", params)
288
333
 
289
- def mints(
334
+ def deposits(
335
+ self,
336
+ symbol0: str | None = None,
337
+ symbol1: str | None = None,
338
+ fee: int | None = None,
339
+ ) -> AsyncQueryBuilder:
340
+ """Start a query for Uniswap V3 deposit events."""
341
+ params: dict[str, Any] = {}
342
+ if symbol0:
343
+ params["symbol0"] = symbol0
344
+ if symbol1:
345
+ params["symbol1"] = symbol1
346
+ if fee:
347
+ params["fee"] = fee
348
+ return AsyncQueryBuilder(self._client, "/uniswap/events/deposit", params)
349
+
350
+ def withdrawals(
290
351
  self,
291
352
  symbol0: str | None = None,
292
353
  symbol1: str | None = None,
293
354
  fee: int | None = None,
294
355
  ) -> AsyncQueryBuilder:
295
- """Start a query for Uniswap V3 mint events."""
356
+ """Start a query for Uniswap V3 withdrawal events."""
296
357
  params: dict[str, Any] = {}
297
358
  if symbol0:
298
359
  params["symbol0"] = symbol0
@@ -300,15 +361,15 @@ class AsyncUniswapProtocol:
300
361
  params["symbol1"] = symbol1
301
362
  if fee:
302
363
  params["fee"] = fee
303
- return AsyncQueryBuilder(self._client, "/uniswap/events/mint", params)
364
+ return AsyncQueryBuilder(self._client, "/uniswap/events/withdraw", params)
304
365
 
305
- def burns(
366
+ def collects(
306
367
  self,
307
368
  symbol0: str | None = None,
308
369
  symbol1: str | None = None,
309
370
  fee: int | None = None,
310
371
  ) -> AsyncQueryBuilder:
311
- """Start a query for Uniswap V3 burn events."""
372
+ """Start a query for Uniswap V3 collect events."""
312
373
  params: dict[str, Any] = {}
313
374
  if symbol0:
314
375
  params["symbol0"] = symbol0
@@ -316,7 +377,7 @@ class AsyncUniswapProtocol:
316
377
  params["symbol1"] = symbol1
317
378
  if fee:
318
379
  params["fee"] = fee
319
- return AsyncQueryBuilder(self._client, "/uniswap/events/burn", params)
380
+ return AsyncQueryBuilder(self._client, "/uniswap/events/collect", params)
320
381
 
321
382
 
322
383
  class AsyncLidoProtocol:
@@ -326,12 +387,24 @@ class AsyncLidoProtocol:
326
387
  self._client = client
327
388
 
328
389
  def deposits(self) -> AsyncQueryBuilder:
329
- """Start a query for Lido deposit events."""
390
+ """Start a query for Lido deposit events (ETH L1 only)."""
330
391
  return AsyncQueryBuilder(self._client, "/lido/events/deposit")
331
392
 
332
- def withdrawals(self) -> AsyncQueryBuilder:
333
- """Start a query for Lido withdrawal events."""
334
- return AsyncQueryBuilder(self._client, "/lido/events/withdraw")
393
+ def withdrawal_requests(self) -> AsyncQueryBuilder:
394
+ """Start a query for Lido withdrawal request events (ETH L1 only)."""
395
+ return AsyncQueryBuilder(self._client, "/lido/events/withdrawal_request")
396
+
397
+ def withdrawals_claimed(self) -> AsyncQueryBuilder:
398
+ """Start a query for Lido claimed withdrawal events (ETH L1 only)."""
399
+ return AsyncQueryBuilder(self._client, "/lido/events/withdrawal_claimed")
400
+
401
+ def l2_deposits(self) -> AsyncQueryBuilder:
402
+ """Start a query for Lido L2 deposit events."""
403
+ return AsyncQueryBuilder(self._client, "/lido/events/l2_deposit")
404
+
405
+ def l2_withdrawal_requests(self) -> AsyncQueryBuilder:
406
+ """Start a query for Lido L2 withdrawal request events."""
407
+ return AsyncQueryBuilder(self._client, "/lido/events/l2_withdrawal_request")
335
408
 
336
409
 
337
410
  class AsyncStaderProtocol:
@@ -344,9 +417,13 @@ class AsyncStaderProtocol:
344
417
  """Start a query for Stader deposit events."""
345
418
  return AsyncQueryBuilder(self._client, "/stader/events/deposit")
346
419
 
420
+ def withdrawal_requests(self) -> AsyncQueryBuilder:
421
+ """Start a query for Stader withdrawal request events."""
422
+ return AsyncQueryBuilder(self._client, "/stader/events/withdrawal_request")
423
+
347
424
  def withdrawals(self) -> AsyncQueryBuilder:
348
425
  """Start a query for Stader withdrawal events."""
349
- return AsyncQueryBuilder(self._client, "/stader/events/withdraw")
426
+ return AsyncQueryBuilder(self._client, "/stader/events/withdrawal")
350
427
 
351
428
 
352
429
  class AsyncThresholdProtocol:
@@ -355,10 +432,18 @@ class AsyncThresholdProtocol:
355
432
  def __init__(self, client: "BaseClient"):
356
433
  self._client = client
357
434
 
358
- def mints(self) -> AsyncQueryBuilder:
359
- """Start a query for tBTC mint events."""
360
- return AsyncQueryBuilder(self._client, "/threshold/events/mint")
435
+ def deposit_requests(self) -> AsyncQueryBuilder:
436
+ """Start a query for tBTC deposit request events."""
437
+ return AsyncQueryBuilder(self._client, "/threshold/events/deposit_request")
361
438
 
362
- def burns(self) -> AsyncQueryBuilder:
363
- """Start a query for tBTC burn events."""
364
- return AsyncQueryBuilder(self._client, "/threshold/events/burn")
439
+ def deposits(self) -> AsyncQueryBuilder:
440
+ """Start a query for tBTC deposit events."""
441
+ return AsyncQueryBuilder(self._client, "/threshold/events/deposit")
442
+
443
+ def withdrawal_requests(self) -> AsyncQueryBuilder:
444
+ """Start a query for tBTC withdrawal request events."""
445
+ return AsyncQueryBuilder(self._client, "/threshold/events/withdrawal_request")
446
+
447
+ def withdrawals(self) -> AsyncQueryBuilder:
448
+ """Start a query for tBTC withdrawal events."""
449
+ return AsyncQueryBuilder(self._client, "/threshold/events/withdrawal")
defistream/query.py CHANGED
@@ -2,13 +2,11 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Any, Generic, TypeVar
5
+ from typing import TYPE_CHECKING, Any
6
6
 
7
7
  if TYPE_CHECKING:
8
8
  from .client import BaseClient
9
9
 
10
- T = TypeVar("T")
11
-
12
10
 
13
11
  class QueryBuilder:
14
12
  """
@@ -20,7 +18,7 @@ class QueryBuilder:
20
18
  - as_file() - saves to CSV, Parquet, or JSON file
21
19
 
22
20
  Example:
23
- query = client.erc20.transfers("USDT").network("ETH").start_block(24000000).end_block(24100000)
21
+ query = client.erc20.transfers("USDT").network("ETH").block_range(21000000, 21010000)
24
22
  query = query.min_amount(1000).sender("0x...")
25
23
  df = query.as_df() # pandas DataFrame
26
24
  df = query.as_df("polars") # polars DataFrame
@@ -51,7 +49,7 @@ class QueryBuilder:
51
49
 
52
50
  # Network and block range
53
51
  def network(self, network: str) -> "QueryBuilder":
54
- """Set the network (ETH, ARB, BASE, OP, etc.)."""
52
+ """Set the network (ETH, ARB, BASE, OP, POLYGON, etc.)."""
55
53
  return self._copy_with(network=network)
56
54
 
57
55
  def start_block(self, block: int) -> "QueryBuilder":
@@ -79,13 +77,13 @@ class QueryBuilder:
79
77
  """Set both start and end times."""
80
78
  return self._copy_with(since=start, until=end)
81
79
 
82
- # Common filters
80
+ # ERC20 and Native Token filters
83
81
  def sender(self, address: str) -> "QueryBuilder":
84
- """Filter by sender address."""
82
+ """Filter by sender address (ERC20, Native Token)."""
85
83
  return self._copy_with(sender=address)
86
84
 
87
85
  def receiver(self, address: str) -> "QueryBuilder":
88
- """Filter by receiver address."""
86
+ """Filter by receiver address (ERC20, Native Token)."""
89
87
  return self._copy_with(receiver=address)
90
88
 
91
89
  def from_address(self, address: str) -> "QueryBuilder":
@@ -97,52 +95,40 @@ class QueryBuilder:
97
95
  return self.receiver(address)
98
96
 
99
97
  def min_amount(self, amount: float) -> "QueryBuilder":
100
- """Filter by minimum amount."""
98
+ """Filter by minimum amount (ERC20, Native Token)."""
101
99
  return self._copy_with(min_amount=amount)
102
100
 
101
+ def max_amount(self, amount: float) -> "QueryBuilder":
102
+ """Filter by maximum amount (ERC20, Native Token)."""
103
+ return self._copy_with(max_amount=amount)
104
+
103
105
  # ERC20 specific
104
106
  def token(self, symbol: str) -> "QueryBuilder":
105
- """Set token symbol (for ERC20)."""
107
+ """Set token symbol or address (ERC20)."""
106
108
  return self._copy_with(token=symbol)
107
109
 
108
- def owner(self, address: str) -> "QueryBuilder":
109
- """Filter by owner address (for approvals)."""
110
- return self._copy_with(owner=address)
111
-
112
- def spender(self, address: str) -> "QueryBuilder":
113
- """Filter by spender address (for approvals)."""
114
- return self._copy_with(spender=address)
110
+ def decimals(self, decimals: int) -> "QueryBuilder":
111
+ """Set token decimals when using custom address (ERC20). Default: 18."""
112
+ return self._copy_with(decimals=decimals)
115
113
 
116
114
  # AAVE specific
117
- def user(self, address: str) -> "QueryBuilder":
118
- """Filter by user address (for AAVE)."""
119
- return self._copy_with(user=address)
120
-
121
- def reserve(self, address: str) -> "QueryBuilder":
122
- """Filter by reserve address (for AAVE)."""
123
- return self._copy_with(reserve=address)
124
-
125
- def liquidator(self, address: str) -> "QueryBuilder":
126
- """Filter by liquidator address (for AAVE liquidations)."""
127
- return self._copy_with(liquidator=address)
115
+ def eth_market_type(self, market_type: str) -> "QueryBuilder":
116
+ """Set AAVE market type for ETH network: 'Core', 'Prime', or 'EtherFi'. Default: 'Core'."""
117
+ return self._copy_with(eth_market_type=market_type)
128
118
 
129
119
  # Uniswap specific
130
120
  def symbol0(self, symbol: str) -> "QueryBuilder":
131
- """Set first token symbol (for Uniswap)."""
121
+ """Set first token symbol (Uniswap)."""
132
122
  return self._copy_with(symbol0=symbol)
133
123
 
134
124
  def symbol1(self, symbol: str) -> "QueryBuilder":
135
- """Set second token symbol (for Uniswap)."""
125
+ """Set second token symbol (Uniswap)."""
136
126
  return self._copy_with(symbol1=symbol)
137
127
 
138
128
  def fee(self, fee_tier: int) -> "QueryBuilder":
139
- """Set fee tier (for Uniswap): 100, 500, 3000, 10000."""
129
+ """Set fee tier (Uniswap): 100, 500, 3000, 10000."""
140
130
  return self._copy_with(fee=fee_tier)
141
131
 
142
- def pool(self, address: str) -> "QueryBuilder":
143
- """Set pool address (for Uniswap)."""
144
- return self._copy_with(pool=address)
145
-
146
132
  # Verbose mode
147
133
  def verbose(self, enabled: bool = True) -> "QueryBuilder":
148
134
  """Include all metadata fields (tx_hash, tx_id, log_index, network, name)."""
@@ -161,7 +147,7 @@ class QueryBuilder:
161
147
  """
162
148
  Execute query and return results as list of dictionaries.
163
149
 
164
- Uses JSON format from API.
150
+ Uses JSON format from API. Limited to 10,000 blocks.
165
151
 
166
152
  Returns:
167
153
  List of event dictionaries
@@ -253,7 +239,7 @@ class AsyncQueryBuilder:
253
239
  - as_file() - saves to CSV, Parquet, or JSON file
254
240
 
255
241
  Example:
256
- query = client.erc20.transfers("USDT").network("ETH").start_block(24000000).end_block(24100000)
242
+ query = client.erc20.transfers("USDT").network("ETH").block_range(21000000, 21010000)
257
243
  df = await query.as_df() # pandas DataFrame
258
244
  df = await query.as_df("polars") # polars DataFrame
259
245
  await query.as_file("transfers.csv") # save to CSV
@@ -283,7 +269,7 @@ class AsyncQueryBuilder:
283
269
 
284
270
  # Network and block range
285
271
  def network(self, network: str) -> "AsyncQueryBuilder":
286
- """Set the network (ETH, ARB, BASE, OP, etc.)."""
272
+ """Set the network (ETH, ARB, BASE, OP, POLYGON, etc.)."""
287
273
  return self._copy_with(network=network)
288
274
 
289
275
  def start_block(self, block: int) -> "AsyncQueryBuilder":
@@ -311,13 +297,13 @@ class AsyncQueryBuilder:
311
297
  """Set both start and end times."""
312
298
  return self._copy_with(since=start, until=end)
313
299
 
314
- # Common filters
300
+ # ERC20 and Native Token filters
315
301
  def sender(self, address: str) -> "AsyncQueryBuilder":
316
- """Filter by sender address."""
302
+ """Filter by sender address (ERC20, Native Token)."""
317
303
  return self._copy_with(sender=address)
318
304
 
319
305
  def receiver(self, address: str) -> "AsyncQueryBuilder":
320
- """Filter by receiver address."""
306
+ """Filter by receiver address (ERC20, Native Token)."""
321
307
  return self._copy_with(receiver=address)
322
308
 
323
309
  def from_address(self, address: str) -> "AsyncQueryBuilder":
@@ -329,52 +315,40 @@ class AsyncQueryBuilder:
329
315
  return self.receiver(address)
330
316
 
331
317
  def min_amount(self, amount: float) -> "AsyncQueryBuilder":
332
- """Filter by minimum amount."""
318
+ """Filter by minimum amount (ERC20, Native Token)."""
333
319
  return self._copy_with(min_amount=amount)
334
320
 
321
+ def max_amount(self, amount: float) -> "AsyncQueryBuilder":
322
+ """Filter by maximum amount (ERC20, Native Token)."""
323
+ return self._copy_with(max_amount=amount)
324
+
335
325
  # ERC20 specific
336
326
  def token(self, symbol: str) -> "AsyncQueryBuilder":
337
- """Set token symbol (for ERC20)."""
327
+ """Set token symbol or address (ERC20)."""
338
328
  return self._copy_with(token=symbol)
339
329
 
340
- def owner(self, address: str) -> "AsyncQueryBuilder":
341
- """Filter by owner address (for approvals)."""
342
- return self._copy_with(owner=address)
343
-
344
- def spender(self, address: str) -> "AsyncQueryBuilder":
345
- """Filter by spender address (for approvals)."""
346
- return self._copy_with(spender=address)
330
+ def decimals(self, decimals: int) -> "AsyncQueryBuilder":
331
+ """Set token decimals when using custom address (ERC20). Default: 18."""
332
+ return self._copy_with(decimals=decimals)
347
333
 
348
334
  # AAVE specific
349
- def user(self, address: str) -> "AsyncQueryBuilder":
350
- """Filter by user address (for AAVE)."""
351
- return self._copy_with(user=address)
352
-
353
- def reserve(self, address: str) -> "AsyncQueryBuilder":
354
- """Filter by reserve address (for AAVE)."""
355
- return self._copy_with(reserve=address)
356
-
357
- def liquidator(self, address: str) -> "AsyncQueryBuilder":
358
- """Filter by liquidator address (for AAVE liquidations)."""
359
- return self._copy_with(liquidator=address)
335
+ def eth_market_type(self, market_type: str) -> "AsyncQueryBuilder":
336
+ """Set AAVE market type for ETH network: 'Core', 'Prime', or 'EtherFi'. Default: 'Core'."""
337
+ return self._copy_with(eth_market_type=market_type)
360
338
 
361
339
  # Uniswap specific
362
340
  def symbol0(self, symbol: str) -> "AsyncQueryBuilder":
363
- """Set first token symbol (for Uniswap)."""
341
+ """Set first token symbol (Uniswap)."""
364
342
  return self._copy_with(symbol0=symbol)
365
343
 
366
344
  def symbol1(self, symbol: str) -> "AsyncQueryBuilder":
367
- """Set second token symbol (for Uniswap)."""
345
+ """Set second token symbol (Uniswap)."""
368
346
  return self._copy_with(symbol1=symbol)
369
347
 
370
348
  def fee(self, fee_tier: int) -> "AsyncQueryBuilder":
371
- """Set fee tier (for Uniswap): 100, 500, 3000, 10000."""
349
+ """Set fee tier (Uniswap): 100, 500, 3000, 10000."""
372
350
  return self._copy_with(fee=fee_tier)
373
351
 
374
- def pool(self, address: str) -> "AsyncQueryBuilder":
375
- """Set pool address (for Uniswap)."""
376
- return self._copy_with(pool=address)
377
-
378
352
  # Verbose mode
379
353
  def verbose(self, enabled: bool = True) -> "AsyncQueryBuilder":
380
354
  """Include all metadata fields (tx_hash, tx_id, log_index, network, name)."""
@@ -393,7 +367,7 @@ class AsyncQueryBuilder:
393
367
  """
394
368
  Execute query and return results as list of dictionaries.
395
369
 
396
- Uses JSON format from API.
370
+ Uses JSON format from API. Limited to 10,000 blocks.
397
371
 
398
372
  Returns:
399
373
  List of event dictionaries
@@ -405,8 +379,6 @@ class AsyncQueryBuilder:
405
379
  """
406
380
  Execute query and return results as DataFrame.
407
381
 
408
- Uses Parquet format from API for efficiency, then converts to DataFrame.
409
-
410
382
  Args:
411
383
  library: DataFrame library to use - "pandas" (default) or "polars"
412
384
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: defistream
3
- Version: 1.0.0
3
+ Version: 1.0.2
4
4
  Summary: Python client for the DeFiStream API
5
5
  Project-URL: Homepage, https://defistream.dev
6
6
  Project-URL: Documentation, https://docs.defistream.dev
@@ -34,7 +34,11 @@ Description-Content-Type: text/markdown
34
34
 
35
35
  # DeFiStream Python Client
36
36
 
37
- Official Python client for the [DeFiStream API](https://defistream.dev) - access historical DeFi events from 45+ EVM networks.
37
+ Official Python client for the [DeFiStream API](https://defistream.dev).
38
+
39
+ ## Getting an API Key
40
+
41
+ To use the DeFiStream API, you need to sign up for an account at [defistream.dev](https://defistream.dev) to obtain your API key.
38
42
 
39
43
  ## Installation
40
44
 
@@ -61,44 +65,41 @@ client = DeFiStream()
61
65
  client = DeFiStream(api_key="dsk_your_api_key")
62
66
 
63
67
  # Query ERC20 transfers using builder pattern
64
- transfers = (
68
+ df = (
65
69
  client.erc20.transfers("USDT")
66
70
  .network("ETH")
67
- .start_block(24000000)
68
- .end_block(24100000)
69
- .as_dict()
71
+ .block_range(21000000, 21010000)
72
+ .as_df()
70
73
  )
71
74
 
72
- for transfer in transfers:
73
- print(f"{transfer['sender']} -> {transfer['receiver']}: {transfer['amount']}")
75
+ print(df.head())
74
76
  ```
75
77
 
76
78
  ## Features
77
79
 
78
80
  - **Builder pattern**: Fluent query API with chainable methods
79
81
  - **Type-safe**: Full type hints and Pydantic models
80
- - **Multiple formats**: JSON, CSV, Parquet, pandas DataFrame, polars DataFrame
82
+ - **Multiple formats**: DataFrame (pandas/polars), CSV, Parquet, JSON
81
83
  - **Async support**: Native async/await with `AsyncDeFiStream`
82
- - **All protocols**: AAVE, Uniswap, Lido, ERC20, Native tokens, and more
83
- - **Verbose mode**: Include all metadata fields (tx_hash, tx_id, log_index, network, name)
84
+ - **All protocols**: ERC20, AAVE, Uniswap, Lido, Stader, Threshold, Native tokens
84
85
 
85
86
  ## Supported Protocols
86
87
 
87
88
  | Protocol | Events |
88
89
  |----------|--------|
89
- | ERC20 | `transfers`, `approvals` |
90
+ | ERC20 | `transfers` |
90
91
  | Native Token | `transfers` |
91
- | AAVE V3 | `deposits`, `withdrawals`, `borrows`, `repays`, `liquidations` |
92
- | Uniswap V3 | `swaps`, `mints`, `burns` |
93
- | Lido | `deposits`, `withdrawals` |
94
- | Stader | `deposits`, `withdrawals` |
95
- | Threshold | `mints`, `burns` |
92
+ | AAVE V3 | `deposits`, `withdrawals`, `borrows`, `repays`, `flashloans`, `liquidations` |
93
+ | Uniswap V3 | `swaps`, `deposits`, `withdrawals`, `collects` |
94
+ | Lido | `deposits`, `withdrawal_requests`, `withdrawals_claimed`, `l2_deposits`, `l2_withdrawal_requests` |
95
+ | Stader | `deposits`, `withdrawal_requests`, `withdrawals` |
96
+ | Threshold | `deposit_requests`, `deposits`, `withdrawal_requests`, `withdrawals` |
96
97
 
97
98
  ## Usage Examples
98
99
 
99
100
  ### Builder Pattern
100
101
 
101
- The client uses a fluent builder pattern. The query is only executed when you call a terminal method like `as_dict()`, `as_df()`, or `as_file()`.
102
+ The client uses a fluent builder pattern. The query is only executed when you call a terminal method like `as_df()`, `as_file()`, or `as_dict()`.
102
103
 
103
104
  ```python
104
105
  from defistream import DeFiStream
@@ -108,21 +109,19 @@ client = DeFiStream()
108
109
  # Build query step by step
109
110
  query = client.erc20.transfers("USDT")
110
111
  query = query.network("ETH")
111
- query = query.start_block(24000000)
112
- query = query.end_block(24100000)
112
+ query = query.block_range(21000000, 21010000)
113
113
  query = query.min_amount(1000)
114
114
 
115
- # Execute and get results
116
- transfers = query.as_dict()
115
+ # Execute and get DataFrame
116
+ df = query.as_df()
117
117
 
118
118
  # Or chain everything
119
- transfers = (
119
+ df = (
120
120
  client.erc20.transfers("USDT")
121
121
  .network("ETH")
122
- .start_block(24000000)
123
- .end_block(24100000)
122
+ .block_range(21000000, 21010000)
124
123
  .min_amount(1000)
125
- .as_dict()
124
+ .as_df()
126
125
  )
127
126
  ```
128
127
 
@@ -130,35 +129,21 @@ transfers = (
130
129
 
131
130
  ```python
132
131
  # Get USDT transfers over 10,000 USDT
133
- transfers = (
132
+ df = (
134
133
  client.erc20.transfers("USDT")
135
134
  .network("ETH")
136
- .start_block(24000000)
137
- .end_block(24100000)
135
+ .block_range(21000000, 21010000)
138
136
  .min_amount(10000)
139
- .as_dict()
137
+ .as_df()
140
138
  )
141
139
 
142
140
  # Filter by sender
143
- transfers = (
141
+ df = (
144
142
  client.erc20.transfers("USDT")
145
143
  .network("ETH")
146
- .start_block(24000000)
147
- .end_block(24100000)
144
+ .block_range(21000000, 21010000)
148
145
  .sender("0x28c6c06298d514db089934071355e5743bf21d60")
149
- .as_dict()
150
- )
151
-
152
- # Or use aliases: from_address/to_address
153
- transfers = (
154
- client.erc20.transfers()
155
- .network("ETH")
156
- .start_block(24000000)
157
- .end_block(24100000)
158
- .token("USDC")
159
- .from_address("0x...")
160
- .to_address("0x...")
161
- .as_dict()
146
+ .as_df()
162
147
  )
163
148
  ```
164
149
 
@@ -166,22 +151,20 @@ transfers = (
166
151
 
167
152
  ```python
168
153
  # Get deposits
169
- deposits = (
154
+ df = (
170
155
  client.aave.deposits()
171
156
  .network("ETH")
172
- .start_block(24000000)
173
- .end_block(24100000)
174
- .as_dict()
157
+ .block_range(21000000, 21010000)
158
+ .as_df()
175
159
  )
176
160
 
177
- # Get liquidations for a specific user
178
- liquidations = (
179
- client.aave.liquidations()
161
+ # Use a specific market type on ETH (Core, Prime, or EtherFi)
162
+ df = (
163
+ client.aave.deposits()
180
164
  .network("ETH")
181
- .start_block(24000000)
182
- .end_block(24100000)
183
- .user("0x...")
184
- .as_dict()
165
+ .block_range(21000000, 21010000)
166
+ .eth_market_type("Prime")
167
+ .as_df()
185
168
  )
186
169
  ```
187
170
 
@@ -189,24 +172,22 @@ liquidations = (
189
172
 
190
173
  ```python
191
174
  # Get swaps for WETH/USDC pool with 0.05% fee tier
192
- swaps = (
175
+ df = (
193
176
  client.uniswap.swaps("WETH", "USDC", 500)
194
177
  .network("ETH")
195
- .start_block(24000000)
196
- .end_block(24100000)
197
- .as_dict()
178
+ .block_range(21000000, 21010000)
179
+ .as_df()
198
180
  )
199
181
 
200
182
  # Or build with chain methods
201
- swaps = (
183
+ df = (
202
184
  client.uniswap.swaps()
203
185
  .symbol0("WETH")
204
186
  .symbol1("USDC")
205
187
  .fee(500)
206
188
  .network("ETH")
207
- .start_block(24000000)
208
- .end_block(24100000)
209
- .as_dict()
189
+ .block_range(21000000, 21010000)
190
+ .as_df()
210
191
  )
211
192
  ```
212
193
 
@@ -214,13 +195,12 @@ swaps = (
214
195
 
215
196
  ```python
216
197
  # Get ETH transfers >= 1 ETH
217
- transfers = (
198
+ df = (
218
199
  client.native_token.transfers()
219
200
  .network("ETH")
220
- .start_block(24000000)
221
- .end_block(24100000)
201
+ .block_range(21000000, 21010000)
222
202
  .min_amount(1.0)
223
- .as_dict()
203
+ .as_df()
224
204
  )
225
205
  ```
226
206
 
@@ -230,25 +210,21 @@ By default, responses omit metadata fields to reduce payload size. Use `.verbose
230
210
 
231
211
  ```python
232
212
  # Default: compact response (no tx_hash, tx_id, log_index, network, name)
233
- transfers = (
213
+ df = (
234
214
  client.erc20.transfers("USDT")
235
215
  .network("ETH")
236
- .start_block(24000000)
237
- .end_block(24100000)
238
- .as_dict()
216
+ .block_range(21000000, 21010000)
217
+ .as_df()
239
218
  )
240
- # Returns: [{"block_number": 24000050, "sender": "0x...", "receiver": "0x...", "amount": 1000.0, ...}]
241
219
 
242
220
  # Verbose: includes all metadata fields
243
- transfers = (
221
+ df = (
244
222
  client.erc20.transfers("USDT")
245
223
  .network("ETH")
246
- .start_block(24000000)
247
- .end_block(24100000)
224
+ .block_range(21000000, 21010000)
248
225
  .verbose()
249
- .as_dict()
226
+ .as_df()
250
227
  )
251
- # Returns: [{"name": "TransferEvent", "network": "ETH", "tx_id": "0x...", "tx_hash": "0x...", "log_index": 5, "block_number": 24000050, ...}]
252
228
  ```
253
229
 
254
230
  ### Return as DataFrame
@@ -258,8 +234,7 @@ transfers = (
258
234
  df = (
259
235
  client.erc20.transfers("USDT")
260
236
  .network("ETH")
261
- .start_block(24000000)
262
- .end_block(24100000)
237
+ .block_range(21000000, 21010000)
263
238
  .as_df()
264
239
  )
265
240
 
@@ -267,8 +242,7 @@ df = (
267
242
  df = (
268
243
  client.erc20.transfers("USDT")
269
244
  .network("ETH")
270
- .start_block(24000000)
271
- .end_block(24100000)
245
+ .block_range(21000000, 21010000)
272
246
  .as_df("polars")
273
247
  )
274
248
  ```
@@ -278,43 +252,49 @@ df = (
278
252
  Format is automatically determined by file extension:
279
253
 
280
254
  ```python
281
- # Save as CSV
255
+ # Save as Parquet (recommended for large datasets)
282
256
  (
283
257
  client.erc20.transfers("USDT")
284
258
  .network("ETH")
285
- .start_block(24000000)
286
- .end_block(24100000)
287
- .as_file("transfers.csv")
259
+ .block_range(21000000, 21100000)
260
+ .as_file("transfers.parquet")
288
261
  )
289
262
 
290
- # Save as Parquet
263
+ # Save as CSV
291
264
  (
292
265
  client.erc20.transfers("USDT")
293
266
  .network("ETH")
294
- .start_block(24000000)
295
- .end_block(24100000)
296
- .as_file("transfers.parquet")
267
+ .block_range(21000000, 21100000)
268
+ .as_file("transfers.csv")
297
269
  )
298
270
 
299
271
  # Save as JSON
300
272
  (
301
273
  client.erc20.transfers("USDT")
302
274
  .network("ETH")
303
- .start_block(24000000)
304
- .end_block(24100000)
275
+ .block_range(21000000, 21010000)
305
276
  .as_file("transfers.json")
306
277
  )
278
+ ```
307
279
 
308
- # Explicit format (when path has no extension)
309
- (
280
+ ### Return as Dictionary (JSON)
281
+
282
+ For small queries, you can get results as a list of dictionaries:
283
+
284
+ ```python
285
+ transfers = (
310
286
  client.erc20.transfers("USDT")
311
287
  .network("ETH")
312
- .start_block(24000000)
313
- .end_block(24100000)
314
- .as_file("transfers", format="csv")
288
+ .block_range(21000000, 21010000)
289
+ .as_dict()
315
290
  )
291
+
292
+ for transfer in transfers:
293
+ print(f"{transfer['sender']} -> {transfer['receiver']}: {transfer['amount']}")
316
294
  ```
317
295
 
296
+ > **Note:** `as_dict()` and `as_file("*.json")` use JSON format which has a **10,000 block limit**. For larger block ranges, use `as_df()` or `as_file()` with `.parquet` or `.csv` extensions, which support up to 1,000,000 blocks.
297
+
318
298
  ### Async Usage
319
299
 
320
300
  ```python
@@ -323,41 +303,17 @@ from defistream import AsyncDeFiStream
323
303
 
324
304
  async def main():
325
305
  async with AsyncDeFiStream() as client:
326
- transfers = await (
306
+ df = await (
327
307
  client.erc20.transfers("USDT")
328
308
  .network("ETH")
329
- .start_block(24000000)
330
- .end_block(24100000)
331
- .as_dict()
309
+ .block_range(21000000, 21010000)
310
+ .as_df()
332
311
  )
333
- print(f"Found {len(transfers)} transfers")
312
+ print(f"Found {len(df)} transfers")
334
313
 
335
314
  asyncio.run(main())
336
315
  ```
337
316
 
338
- ### Multiple Networks in Parallel
339
-
340
- ```python
341
- import asyncio
342
- from defistream import AsyncDeFiStream
343
-
344
- async def fetch_all_networks():
345
- async with AsyncDeFiStream() as client:
346
- networks = ["ETH", "ARB", "BASE", "OP"]
347
- tasks = [
348
- client.erc20.transfers("USDC")
349
- .network(net)
350
- .start_block(24000000)
351
- .end_block(24100000)
352
- .as_dict()
353
- for net in networks
354
- ]
355
- results = await asyncio.gather(*tasks)
356
- return dict(zip(networks, results))
357
-
358
- all_transfers = asyncio.run(fetch_all_networks())
359
- ```
360
-
361
317
  ## Configuration
362
318
 
363
319
  ### Environment Variables
@@ -402,12 +358,11 @@ from defistream.exceptions import (
402
358
  client = DeFiStream()
403
359
 
404
360
  try:
405
- transfers = (
361
+ df = (
406
362
  client.erc20.transfers("USDT")
407
363
  .network("ETH")
408
- .start_block(24000000)
409
- .end_block(24100000)
410
- .as_dict()
364
+ .block_range(21000000, 21010000)
365
+ .as_df()
411
366
  )
412
367
  except AuthenticationError:
413
368
  print("Invalid API key")
@@ -426,12 +381,11 @@ except DeFiStreamError as e:
426
381
  Access rate limit and quota information:
427
382
 
428
383
  ```python
429
- transfers = (
384
+ df = (
430
385
  client.erc20.transfers("USDT")
431
386
  .network("ETH")
432
- .start_block(24000000)
433
- .end_block(24100000)
434
- .as_dict()
387
+ .block_range(21000000, 21010000)
388
+ .as_df()
435
389
  )
436
390
 
437
391
  # Access response metadata
@@ -446,7 +400,7 @@ print(f"Request cost: {client.last_response.request_cost}")
446
400
 
447
401
  | Method | Description |
448
402
  |--------|-------------|
449
- | `.network(net)` | Set network (ETH, ARB, BASE, OP, etc.) |
403
+ | `.network(net)` | Set network (ETH, ARB, BASE, OP, POLYGON, etc.) |
450
404
  | `.start_block(n)` | Set starting block number |
451
405
  | `.end_block(n)` | Set ending block number |
452
406
  | `.block_range(start, end)` | Set both start and end blocks |
@@ -455,35 +409,30 @@ print(f"Request cost: {client.last_response.request_cost}")
455
409
  | `.time_range(start, end)` | Set both start and end times |
456
410
  | `.verbose()` | Include all metadata fields |
457
411
 
458
- ### Filter Methods
412
+ ### Protocol-Specific Parameters
459
413
 
460
414
  | Method | Protocols | Description |
461
415
  |--------|-----------|-------------|
416
+ | `.token(symbol)` | ERC20 | Token symbol (USDT, USDC) or contract address |
417
+ | `.decimals(n)` | ERC20 | Token decimals when using custom address (default: 18) |
462
418
  | `.sender(addr)` | ERC20, Native | Filter by sender address |
463
419
  | `.receiver(addr)` | ERC20, Native | Filter by receiver address |
464
- | `.from_address(addr)` | ERC20, Native | Alias for sender |
465
- | `.to_address(addr)` | ERC20, Native | Alias for receiver |
466
420
  | `.min_amount(amt)` | ERC20, Native | Minimum transfer amount |
467
- | `.token(symbol)` | ERC20 | Token symbol (USDT, USDC, etc.) |
468
- | `.owner(addr)` | ERC20 Approvals, Lido | Filter by owner |
469
- | `.spender(addr)` | ERC20 Approvals | Filter by spender |
470
- | `.user(addr)` | AAVE | Filter by user |
471
- | `.reserve(addr)` | AAVE | Filter by reserve |
472
- | `.liquidator(addr)` | AAVE Liquidations | Filter by liquidator |
473
- | `.symbol0(sym)` | Uniswap | First token symbol |
474
- | `.symbol1(sym)` | Uniswap | Second token symbol |
475
- | `.fee(tier)` | Uniswap | Fee tier (100, 500, 3000, 10000) |
476
- | `.pool(addr)` | Uniswap | Pool address |
421
+ | `.max_amount(amt)` | ERC20, Native | Maximum transfer amount |
422
+ | `.eth_market_type(type)` | AAVE | Market type for ETH: 'Core', 'Prime', 'EtherFi' |
423
+ | `.symbol0(sym)` | Uniswap | First token symbol (required) |
424
+ | `.symbol1(sym)` | Uniswap | Second token symbol (required) |
425
+ | `.fee(tier)` | Uniswap | Fee tier: 100, 500, 3000, 10000 (required) |
477
426
 
478
427
  ### Terminal Methods
479
428
 
480
429
  | Method | Description |
481
430
  |--------|-------------|
482
- | `.as_dict()` | Execute and return list of dicts (JSON) |
483
431
  | `.as_df()` | Execute and return pandas DataFrame |
484
432
  | `.as_df("polars")` | Execute and return polars DataFrame |
485
433
  | `.as_file(path)` | Execute and save to file (format from extension) |
486
434
  | `.as_file(path, format="csv")` | Execute and save with explicit format |
435
+ | `.as_dict()` | Execute and return list of dicts (JSON, 10K block limit) |
487
436
 
488
437
  ## License
489
438
 
@@ -0,0 +1,11 @@
1
+ defistream/__init__.py,sha256=RUAlky12Gxi0hYBUeXJ32qkhku-BLs8cOqZCpC6nZE0,1680
2
+ defistream/client.py,sha256=Ku8ouDbM6Mx4lVmqvBwNvNt-h2FkvqauPMSjKyPkjU4,12717
3
+ defistream/exceptions.py,sha256=_GxZQ18_YvXFtmNHeddWV8fHPIllHgFeP7fP0CmHF1k,1492
4
+ defistream/models.py,sha256=JiG4IUq19HIANz9MHQCkaE6onGNyNzXcbdJmosrHsw0,3812
5
+ defistream/protocols.py,sha256=5_bYd46lDy-mK6LZ8sTGW0Z2IVH4g0cQ5rBbbOXsw0U,15368
6
+ defistream/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ defistream/query.py,sha256=cOGba8MQNFKXTs39csD81vrMW76c9O3-S40R0KAMyCA,17158
8
+ defistream-1.0.2.dist-info/METADATA,sha256=MSChxyWWx6vCUALDfZFybRLcqJsKtyi56N4eY-i2vyE,10950
9
+ defistream-1.0.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
10
+ defistream-1.0.2.dist-info/licenses/LICENSE,sha256=72DWAof8dMePfFQmfaswClW5d-sE6k7p-7VpuSKLmU4,1067
11
+ defistream-1.0.2.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- defistream/__init__.py,sha256=nXlmtbfyy4VrbZ8PRFzUW49R6DukTRZIxeeph_9k6UY,1827
2
- defistream/client.py,sha256=Ku8ouDbM6Mx4lVmqvBwNvNt-h2FkvqauPMSjKyPkjU4,12717
3
- defistream/exceptions.py,sha256=_GxZQ18_YvXFtmNHeddWV8fHPIllHgFeP7fP0CmHF1k,1492
4
- defistream/models.py,sha256=JiG4IUq19HIANz9MHQCkaE6onGNyNzXcbdJmosrHsw0,3812
5
- defistream/protocols.py,sha256=b9zX0RUaw9mwZA-rPCPfpRisN5X-mdwmXSoTPYS-ius,11811
6
- defistream/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- defistream/query.py,sha256=73vu8uXBdiFqGKoU0nDHDQ8emLnt1HVJMmvrl--Hzmg,17791
8
- defistream-1.0.0.dist-info/METADATA,sha256=m6_u2yhrLNNHnm8HthaDx0pYpGtENY-CO7bz-qQeh94,12079
9
- defistream-1.0.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
10
- defistream-1.0.0.dist-info/licenses/LICENSE,sha256=72DWAof8dMePfFQmfaswClW5d-sE6k7p-7VpuSKLmU4,1067
11
- defistream-1.0.0.dist-info/RECORD,,