defistream 1.0.0__tar.gz
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-1.0.0/.gitignore +51 -0
- defistream-1.0.0/LICENSE +21 -0
- defistream-1.0.0/PKG-INFO +490 -0
- defistream-1.0.0/README.md +456 -0
- defistream-1.0.0/pyproject.toml +57 -0
- defistream-1.0.0/sample_usage.py +11 -0
- defistream-1.0.0/src/defistream/__init__.py +81 -0
- defistream-1.0.0/src/defistream/client.py +380 -0
- defistream-1.0.0/src/defistream/exceptions.py +65 -0
- defistream-1.0.0/src/defistream/models.py +174 -0
- defistream-1.0.0/src/defistream/protocols.py +364 -0
- defistream-1.0.0/src/defistream/py.typed +0 -0
- defistream-1.0.0/src/defistream/query.py +477 -0
- defistream-1.0.0/tests/__init__.py +0 -0
- defistream-1.0.0/tests/test_client.py +359 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
.Python
|
|
8
|
+
build/
|
|
9
|
+
develop-eggs/
|
|
10
|
+
dist/
|
|
11
|
+
downloads/
|
|
12
|
+
eggs/
|
|
13
|
+
.eggs/
|
|
14
|
+
lib/
|
|
15
|
+
lib64/
|
|
16
|
+
parts/
|
|
17
|
+
sdist/
|
|
18
|
+
var/
|
|
19
|
+
wheels/
|
|
20
|
+
*.egg-info/
|
|
21
|
+
.installed.cfg
|
|
22
|
+
*.egg
|
|
23
|
+
|
|
24
|
+
# Virtual environments
|
|
25
|
+
venv/
|
|
26
|
+
ENV/
|
|
27
|
+
env/
|
|
28
|
+
.venv/
|
|
29
|
+
|
|
30
|
+
# IDE
|
|
31
|
+
.idea/
|
|
32
|
+
.vscode/
|
|
33
|
+
*.swp
|
|
34
|
+
*.swo
|
|
35
|
+
|
|
36
|
+
# Testing
|
|
37
|
+
.pytest_cache/
|
|
38
|
+
.coverage
|
|
39
|
+
htmlcov/
|
|
40
|
+
.tox/
|
|
41
|
+
.nox/
|
|
42
|
+
|
|
43
|
+
# Type checking
|
|
44
|
+
.mypy_cache/
|
|
45
|
+
|
|
46
|
+
# Jupyter
|
|
47
|
+
.ipynb_checkpoints/
|
|
48
|
+
|
|
49
|
+
# Environment
|
|
50
|
+
.env
|
|
51
|
+
.env.local
|
defistream-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DeFiStream
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: defistream
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python client for the DeFiStream API
|
|
5
|
+
Project-URL: Homepage, https://defistream.dev
|
|
6
|
+
Project-URL: Documentation, https://docs.defistream.dev
|
|
7
|
+
Project-URL: Repository, https://github.com/Eren-Nevin/DeFiStream_PythonClient
|
|
8
|
+
Author-email: DeFiStream <support@defistream.dev>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: api,blockchain,crypto,defi,ethereum,web3
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Requires-Dist: httpx>=0.25.0
|
|
24
|
+
Requires-Dist: pandas>=2.0.0
|
|
25
|
+
Requires-Dist: pyarrow>=14.0.0
|
|
26
|
+
Requires-Dist: pydantic>=2.0.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: python-dotenv>=1.0.0; extra == 'dev'
|
|
31
|
+
Provides-Extra: polars
|
|
32
|
+
Requires-Dist: polars>=0.20.0; extra == 'polars'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# DeFiStream Python Client
|
|
36
|
+
|
|
37
|
+
Official Python client for the [DeFiStream API](https://defistream.dev) - access historical DeFi events from 45+ EVM networks.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install defistream
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
This includes pandas and pyarrow by default for DataFrame support.
|
|
46
|
+
|
|
47
|
+
With polars support (in addition to pandas):
|
|
48
|
+
```bash
|
|
49
|
+
pip install defistream[polars]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from defistream import DeFiStream
|
|
56
|
+
|
|
57
|
+
# Initialize client (reads DEFISTREAM_API_KEY from environment if not provided)
|
|
58
|
+
client = DeFiStream()
|
|
59
|
+
|
|
60
|
+
# Or with explicit API key
|
|
61
|
+
client = DeFiStream(api_key="dsk_your_api_key")
|
|
62
|
+
|
|
63
|
+
# Query ERC20 transfers using builder pattern
|
|
64
|
+
transfers = (
|
|
65
|
+
client.erc20.transfers("USDT")
|
|
66
|
+
.network("ETH")
|
|
67
|
+
.start_block(24000000)
|
|
68
|
+
.end_block(24100000)
|
|
69
|
+
.as_dict()
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
for transfer in transfers:
|
|
73
|
+
print(f"{transfer['sender']} -> {transfer['receiver']}: {transfer['amount']}")
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Features
|
|
77
|
+
|
|
78
|
+
- **Builder pattern**: Fluent query API with chainable methods
|
|
79
|
+
- **Type-safe**: Full type hints and Pydantic models
|
|
80
|
+
- **Multiple formats**: JSON, CSV, Parquet, pandas DataFrame, polars DataFrame
|
|
81
|
+
- **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
|
+
|
|
85
|
+
## Supported Protocols
|
|
86
|
+
|
|
87
|
+
| Protocol | Events |
|
|
88
|
+
|----------|--------|
|
|
89
|
+
| ERC20 | `transfers`, `approvals` |
|
|
90
|
+
| 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` |
|
|
96
|
+
|
|
97
|
+
## Usage Examples
|
|
98
|
+
|
|
99
|
+
### Builder Pattern
|
|
100
|
+
|
|
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
|
+
|
|
103
|
+
```python
|
|
104
|
+
from defistream import DeFiStream
|
|
105
|
+
|
|
106
|
+
client = DeFiStream()
|
|
107
|
+
|
|
108
|
+
# Build query step by step
|
|
109
|
+
query = client.erc20.transfers("USDT")
|
|
110
|
+
query = query.network("ETH")
|
|
111
|
+
query = query.start_block(24000000)
|
|
112
|
+
query = query.end_block(24100000)
|
|
113
|
+
query = query.min_amount(1000)
|
|
114
|
+
|
|
115
|
+
# Execute and get results
|
|
116
|
+
transfers = query.as_dict()
|
|
117
|
+
|
|
118
|
+
# Or chain everything
|
|
119
|
+
transfers = (
|
|
120
|
+
client.erc20.transfers("USDT")
|
|
121
|
+
.network("ETH")
|
|
122
|
+
.start_block(24000000)
|
|
123
|
+
.end_block(24100000)
|
|
124
|
+
.min_amount(1000)
|
|
125
|
+
.as_dict()
|
|
126
|
+
)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### ERC20 Transfers
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
# Get USDT transfers over 10,000 USDT
|
|
133
|
+
transfers = (
|
|
134
|
+
client.erc20.transfers("USDT")
|
|
135
|
+
.network("ETH")
|
|
136
|
+
.start_block(24000000)
|
|
137
|
+
.end_block(24100000)
|
|
138
|
+
.min_amount(10000)
|
|
139
|
+
.as_dict()
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# Filter by sender
|
|
143
|
+
transfers = (
|
|
144
|
+
client.erc20.transfers("USDT")
|
|
145
|
+
.network("ETH")
|
|
146
|
+
.start_block(24000000)
|
|
147
|
+
.end_block(24100000)
|
|
148
|
+
.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()
|
|
162
|
+
)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### AAVE Events
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
# Get deposits
|
|
169
|
+
deposits = (
|
|
170
|
+
client.aave.deposits()
|
|
171
|
+
.network("ETH")
|
|
172
|
+
.start_block(24000000)
|
|
173
|
+
.end_block(24100000)
|
|
174
|
+
.as_dict()
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
# Get liquidations for a specific user
|
|
178
|
+
liquidations = (
|
|
179
|
+
client.aave.liquidations()
|
|
180
|
+
.network("ETH")
|
|
181
|
+
.start_block(24000000)
|
|
182
|
+
.end_block(24100000)
|
|
183
|
+
.user("0x...")
|
|
184
|
+
.as_dict()
|
|
185
|
+
)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Uniswap Swaps
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
# Get swaps for WETH/USDC pool with 0.05% fee tier
|
|
192
|
+
swaps = (
|
|
193
|
+
client.uniswap.swaps("WETH", "USDC", 500)
|
|
194
|
+
.network("ETH")
|
|
195
|
+
.start_block(24000000)
|
|
196
|
+
.end_block(24100000)
|
|
197
|
+
.as_dict()
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
# Or build with chain methods
|
|
201
|
+
swaps = (
|
|
202
|
+
client.uniswap.swaps()
|
|
203
|
+
.symbol0("WETH")
|
|
204
|
+
.symbol1("USDC")
|
|
205
|
+
.fee(500)
|
|
206
|
+
.network("ETH")
|
|
207
|
+
.start_block(24000000)
|
|
208
|
+
.end_block(24100000)
|
|
209
|
+
.as_dict()
|
|
210
|
+
)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Native Token Transfers
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
# Get ETH transfers >= 1 ETH
|
|
217
|
+
transfers = (
|
|
218
|
+
client.native_token.transfers()
|
|
219
|
+
.network("ETH")
|
|
220
|
+
.start_block(24000000)
|
|
221
|
+
.end_block(24100000)
|
|
222
|
+
.min_amount(1.0)
|
|
223
|
+
.as_dict()
|
|
224
|
+
)
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Verbose Mode
|
|
228
|
+
|
|
229
|
+
By default, responses omit metadata fields to reduce payload size. Use `.verbose()` to include all fields:
|
|
230
|
+
|
|
231
|
+
```python
|
|
232
|
+
# Default: compact response (no tx_hash, tx_id, log_index, network, name)
|
|
233
|
+
transfers = (
|
|
234
|
+
client.erc20.transfers("USDT")
|
|
235
|
+
.network("ETH")
|
|
236
|
+
.start_block(24000000)
|
|
237
|
+
.end_block(24100000)
|
|
238
|
+
.as_dict()
|
|
239
|
+
)
|
|
240
|
+
# Returns: [{"block_number": 24000050, "sender": "0x...", "receiver": "0x...", "amount": 1000.0, ...}]
|
|
241
|
+
|
|
242
|
+
# Verbose: includes all metadata fields
|
|
243
|
+
transfers = (
|
|
244
|
+
client.erc20.transfers("USDT")
|
|
245
|
+
.network("ETH")
|
|
246
|
+
.start_block(24000000)
|
|
247
|
+
.end_block(24100000)
|
|
248
|
+
.verbose()
|
|
249
|
+
.as_dict()
|
|
250
|
+
)
|
|
251
|
+
# Returns: [{"name": "TransferEvent", "network": "ETH", "tx_id": "0x...", "tx_hash": "0x...", "log_index": 5, "block_number": 24000050, ...}]
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Return as DataFrame
|
|
255
|
+
|
|
256
|
+
```python
|
|
257
|
+
# As pandas DataFrame (default)
|
|
258
|
+
df = (
|
|
259
|
+
client.erc20.transfers("USDT")
|
|
260
|
+
.network("ETH")
|
|
261
|
+
.start_block(24000000)
|
|
262
|
+
.end_block(24100000)
|
|
263
|
+
.as_df()
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
# As polars DataFrame
|
|
267
|
+
df = (
|
|
268
|
+
client.erc20.transfers("USDT")
|
|
269
|
+
.network("ETH")
|
|
270
|
+
.start_block(24000000)
|
|
271
|
+
.end_block(24100000)
|
|
272
|
+
.as_df("polars")
|
|
273
|
+
)
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Save to File
|
|
277
|
+
|
|
278
|
+
Format is automatically determined by file extension:
|
|
279
|
+
|
|
280
|
+
```python
|
|
281
|
+
# Save as CSV
|
|
282
|
+
(
|
|
283
|
+
client.erc20.transfers("USDT")
|
|
284
|
+
.network("ETH")
|
|
285
|
+
.start_block(24000000)
|
|
286
|
+
.end_block(24100000)
|
|
287
|
+
.as_file("transfers.csv")
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
# Save as Parquet
|
|
291
|
+
(
|
|
292
|
+
client.erc20.transfers("USDT")
|
|
293
|
+
.network("ETH")
|
|
294
|
+
.start_block(24000000)
|
|
295
|
+
.end_block(24100000)
|
|
296
|
+
.as_file("transfers.parquet")
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
# Save as JSON
|
|
300
|
+
(
|
|
301
|
+
client.erc20.transfers("USDT")
|
|
302
|
+
.network("ETH")
|
|
303
|
+
.start_block(24000000)
|
|
304
|
+
.end_block(24100000)
|
|
305
|
+
.as_file("transfers.json")
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
# Explicit format (when path has no extension)
|
|
309
|
+
(
|
|
310
|
+
client.erc20.transfers("USDT")
|
|
311
|
+
.network("ETH")
|
|
312
|
+
.start_block(24000000)
|
|
313
|
+
.end_block(24100000)
|
|
314
|
+
.as_file("transfers", format="csv")
|
|
315
|
+
)
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Async Usage
|
|
319
|
+
|
|
320
|
+
```python
|
|
321
|
+
import asyncio
|
|
322
|
+
from defistream import AsyncDeFiStream
|
|
323
|
+
|
|
324
|
+
async def main():
|
|
325
|
+
async with AsyncDeFiStream() as client:
|
|
326
|
+
transfers = await (
|
|
327
|
+
client.erc20.transfers("USDT")
|
|
328
|
+
.network("ETH")
|
|
329
|
+
.start_block(24000000)
|
|
330
|
+
.end_block(24100000)
|
|
331
|
+
.as_dict()
|
|
332
|
+
)
|
|
333
|
+
print(f"Found {len(transfers)} transfers")
|
|
334
|
+
|
|
335
|
+
asyncio.run(main())
|
|
336
|
+
```
|
|
337
|
+
|
|
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
|
+
## Configuration
|
|
362
|
+
|
|
363
|
+
### Environment Variables
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
export DEFISTREAM_API_KEY=dsk_your_api_key
|
|
367
|
+
export DEFISTREAM_BASE_URL=https://api.defistream.dev/v1 # optional
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
```python
|
|
371
|
+
from defistream import DeFiStream
|
|
372
|
+
|
|
373
|
+
# API key from environment
|
|
374
|
+
client = DeFiStream()
|
|
375
|
+
|
|
376
|
+
# Or explicit
|
|
377
|
+
client = DeFiStream(api_key="dsk_...", base_url="https://api.defistream.dev/v1")
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### Timeout and Retries
|
|
381
|
+
|
|
382
|
+
```python
|
|
383
|
+
client = DeFiStream(
|
|
384
|
+
api_key="dsk_...",
|
|
385
|
+
timeout=60.0, # seconds
|
|
386
|
+
max_retries=3
|
|
387
|
+
)
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
## Error Handling
|
|
391
|
+
|
|
392
|
+
```python
|
|
393
|
+
from defistream import DeFiStream
|
|
394
|
+
from defistream.exceptions import (
|
|
395
|
+
DeFiStreamError,
|
|
396
|
+
AuthenticationError,
|
|
397
|
+
QuotaExceededError,
|
|
398
|
+
RateLimitError,
|
|
399
|
+
ValidationError
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
client = DeFiStream()
|
|
403
|
+
|
|
404
|
+
try:
|
|
405
|
+
transfers = (
|
|
406
|
+
client.erc20.transfers("USDT")
|
|
407
|
+
.network("ETH")
|
|
408
|
+
.start_block(24000000)
|
|
409
|
+
.end_block(24100000)
|
|
410
|
+
.as_dict()
|
|
411
|
+
)
|
|
412
|
+
except AuthenticationError:
|
|
413
|
+
print("Invalid API key")
|
|
414
|
+
except QuotaExceededError as e:
|
|
415
|
+
print(f"Quota exceeded. Remaining: {e.remaining}")
|
|
416
|
+
except RateLimitError as e:
|
|
417
|
+
print(f"Rate limited. Retry after: {e.retry_after}s")
|
|
418
|
+
except ValidationError as e:
|
|
419
|
+
print(f"Invalid request: {e.message}")
|
|
420
|
+
except DeFiStreamError as e:
|
|
421
|
+
print(f"API error: {e}")
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## Response Headers
|
|
425
|
+
|
|
426
|
+
Access rate limit and quota information:
|
|
427
|
+
|
|
428
|
+
```python
|
|
429
|
+
transfers = (
|
|
430
|
+
client.erc20.transfers("USDT")
|
|
431
|
+
.network("ETH")
|
|
432
|
+
.start_block(24000000)
|
|
433
|
+
.end_block(24100000)
|
|
434
|
+
.as_dict()
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
# Access response metadata
|
|
438
|
+
print(f"Rate limit: {client.last_response.rate_limit}")
|
|
439
|
+
print(f"Remaining quota: {client.last_response.quota_remaining}")
|
|
440
|
+
print(f"Request cost: {client.last_response.request_cost}")
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
## Builder Methods Reference
|
|
444
|
+
|
|
445
|
+
### Common Methods (all protocols)
|
|
446
|
+
|
|
447
|
+
| Method | Description |
|
|
448
|
+
|--------|-------------|
|
|
449
|
+
| `.network(net)` | Set network (ETH, ARB, BASE, OP, etc.) |
|
|
450
|
+
| `.start_block(n)` | Set starting block number |
|
|
451
|
+
| `.end_block(n)` | Set ending block number |
|
|
452
|
+
| `.block_range(start, end)` | Set both start and end blocks |
|
|
453
|
+
| `.start_time(ts)` | Set starting time (ISO format or Unix timestamp) |
|
|
454
|
+
| `.end_time(ts)` | Set ending time (ISO format or Unix timestamp) |
|
|
455
|
+
| `.time_range(start, end)` | Set both start and end times |
|
|
456
|
+
| `.verbose()` | Include all metadata fields |
|
|
457
|
+
|
|
458
|
+
### Filter Methods
|
|
459
|
+
|
|
460
|
+
| Method | Protocols | Description |
|
|
461
|
+
|--------|-----------|-------------|
|
|
462
|
+
| `.sender(addr)` | ERC20, Native | Filter by sender address |
|
|
463
|
+
| `.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
|
+
| `.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 |
|
|
477
|
+
|
|
478
|
+
### Terminal Methods
|
|
479
|
+
|
|
480
|
+
| Method | Description |
|
|
481
|
+
|--------|-------------|
|
|
482
|
+
| `.as_dict()` | Execute and return list of dicts (JSON) |
|
|
483
|
+
| `.as_df()` | Execute and return pandas DataFrame |
|
|
484
|
+
| `.as_df("polars")` | Execute and return polars DataFrame |
|
|
485
|
+
| `.as_file(path)` | Execute and save to file (format from extension) |
|
|
486
|
+
| `.as_file(path, format="csv")` | Execute and save with explicit format |
|
|
487
|
+
|
|
488
|
+
## License
|
|
489
|
+
|
|
490
|
+
MIT License
|