defistream 1.0.6__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 +51 -0
- defistream/client.py +380 -0
- defistream/exceptions.py +65 -0
- defistream/models.py +27 -0
- defistream/protocols.py +449 -0
- defistream/py.typed +0 -0
- defistream/query.py +441 -0
- defistream-1.0.6.dist-info/METADATA +438 -0
- defistream-1.0.6.dist-info/RECORD +11 -0
- defistream-1.0.6.dist-info/WHEEL +4 -0
- defistream-1.0.6.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: defistream
|
|
3
|
+
Version: 1.0.6
|
|
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).
|
|
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.
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install defistream
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
This includes pandas and pyarrow by default for DataFrame support.
|
|
50
|
+
|
|
51
|
+
With polars support (in addition to pandas):
|
|
52
|
+
```bash
|
|
53
|
+
pip install defistream[polars]
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from defistream import DeFiStream
|
|
60
|
+
|
|
61
|
+
# Initialize client (reads DEFISTREAM_API_KEY from environment if not provided)
|
|
62
|
+
client = DeFiStream()
|
|
63
|
+
|
|
64
|
+
# Or with explicit API key
|
|
65
|
+
client = DeFiStream(api_key="dsk_your_api_key")
|
|
66
|
+
|
|
67
|
+
# Query ERC20 transfers using builder pattern
|
|
68
|
+
df = (
|
|
69
|
+
client.erc20.transfers("USDT")
|
|
70
|
+
.network("ETH")
|
|
71
|
+
.block_range(21000000, 21010000)
|
|
72
|
+
.as_df()
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
print(df.head())
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Features
|
|
79
|
+
|
|
80
|
+
- **Builder pattern**: Fluent query API with chainable methods
|
|
81
|
+
- **Type-safe**: Full type hints and Pydantic models
|
|
82
|
+
- **Multiple formats**: DataFrame (pandas/polars), CSV, Parquet, JSON
|
|
83
|
+
- **Async support**: Native async/await with `AsyncDeFiStream`
|
|
84
|
+
- **All protocols**: ERC20, AAVE, Uniswap, Lido, Stader, Threshold, Native tokens
|
|
85
|
+
|
|
86
|
+
## Supported Protocols
|
|
87
|
+
|
|
88
|
+
| Protocol | Events |
|
|
89
|
+
|----------|--------|
|
|
90
|
+
| ERC20 | `transfers` |
|
|
91
|
+
| Native Token | `transfers` |
|
|
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` |
|
|
97
|
+
|
|
98
|
+
## Usage Examples
|
|
99
|
+
|
|
100
|
+
### Builder Pattern
|
|
101
|
+
|
|
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()`.
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from defistream import DeFiStream
|
|
106
|
+
|
|
107
|
+
client = DeFiStream()
|
|
108
|
+
|
|
109
|
+
# Build query step by step
|
|
110
|
+
query = client.erc20.transfers("USDT")
|
|
111
|
+
query = query.network("ETH")
|
|
112
|
+
query = query.block_range(21000000, 21010000)
|
|
113
|
+
query = query.min_amount(1000)
|
|
114
|
+
|
|
115
|
+
# Execute and get DataFrame
|
|
116
|
+
df = query.as_df()
|
|
117
|
+
|
|
118
|
+
# Or chain everything
|
|
119
|
+
df = (
|
|
120
|
+
client.erc20.transfers("USDT")
|
|
121
|
+
.network("ETH")
|
|
122
|
+
.block_range(21000000, 21010000)
|
|
123
|
+
.min_amount(1000)
|
|
124
|
+
.as_df()
|
|
125
|
+
)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### ERC20 Transfers
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
# Get USDT transfers over 10,000 USDT
|
|
132
|
+
df = (
|
|
133
|
+
client.erc20.transfers("USDT")
|
|
134
|
+
.network("ETH")
|
|
135
|
+
.block_range(21000000, 21010000)
|
|
136
|
+
.min_amount(10000)
|
|
137
|
+
.as_df()
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# Filter by sender
|
|
141
|
+
df = (
|
|
142
|
+
client.erc20.transfers("USDT")
|
|
143
|
+
.network("ETH")
|
|
144
|
+
.block_range(21000000, 21010000)
|
|
145
|
+
.sender("0x28c6c06298d514db089934071355e5743bf21d60")
|
|
146
|
+
.as_df()
|
|
147
|
+
)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### AAVE Events
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
# Get deposits
|
|
154
|
+
df = (
|
|
155
|
+
client.aave.deposits()
|
|
156
|
+
.network("ETH")
|
|
157
|
+
.block_range(21000000, 21010000)
|
|
158
|
+
.as_df()
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# Use a specific market type on ETH (Core, Prime, or EtherFi)
|
|
162
|
+
df = (
|
|
163
|
+
client.aave.deposits()
|
|
164
|
+
.network("ETH")
|
|
165
|
+
.block_range(21000000, 21010000)
|
|
166
|
+
.eth_market_type("Prime")
|
|
167
|
+
.as_df()
|
|
168
|
+
)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Uniswap Swaps
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
# Get swaps for WETH/USDC pool with 0.05% fee tier
|
|
175
|
+
df = (
|
|
176
|
+
client.uniswap.swaps("WETH", "USDC", 500)
|
|
177
|
+
.network("ETH")
|
|
178
|
+
.block_range(21000000, 21010000)
|
|
179
|
+
.as_df()
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Or build with chain methods
|
|
183
|
+
df = (
|
|
184
|
+
client.uniswap.swaps()
|
|
185
|
+
.symbol0("WETH")
|
|
186
|
+
.symbol1("USDC")
|
|
187
|
+
.fee(500)
|
|
188
|
+
.network("ETH")
|
|
189
|
+
.block_range(21000000, 21010000)
|
|
190
|
+
.as_df()
|
|
191
|
+
)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Native Token Transfers
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
# Get ETH transfers >= 1 ETH
|
|
198
|
+
df = (
|
|
199
|
+
client.native_token.transfers()
|
|
200
|
+
.network("ETH")
|
|
201
|
+
.block_range(21000000, 21010000)
|
|
202
|
+
.min_amount(1.0)
|
|
203
|
+
.as_df()
|
|
204
|
+
)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Verbose Mode
|
|
208
|
+
|
|
209
|
+
By default, responses omit metadata fields to reduce payload size. Use `.verbose()` to include all fields:
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
# Default: compact response (no tx_hash, tx_id, log_index, network, name)
|
|
213
|
+
df = (
|
|
214
|
+
client.erc20.transfers("USDT")
|
|
215
|
+
.network("ETH")
|
|
216
|
+
.block_range(21000000, 21010000)
|
|
217
|
+
.as_df()
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
# Verbose: includes all metadata fields
|
|
221
|
+
df = (
|
|
222
|
+
client.erc20.transfers("USDT")
|
|
223
|
+
.network("ETH")
|
|
224
|
+
.block_range(21000000, 21010000)
|
|
225
|
+
.verbose()
|
|
226
|
+
.as_df()
|
|
227
|
+
)
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Return as DataFrame
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
# As pandas DataFrame (default)
|
|
234
|
+
df = (
|
|
235
|
+
client.erc20.transfers("USDT")
|
|
236
|
+
.network("ETH")
|
|
237
|
+
.block_range(21000000, 21010000)
|
|
238
|
+
.as_df()
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
# As polars DataFrame
|
|
242
|
+
df = (
|
|
243
|
+
client.erc20.transfers("USDT")
|
|
244
|
+
.network("ETH")
|
|
245
|
+
.block_range(21000000, 21010000)
|
|
246
|
+
.as_df("polars")
|
|
247
|
+
)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Save to File
|
|
251
|
+
|
|
252
|
+
Format is automatically determined by file extension:
|
|
253
|
+
|
|
254
|
+
```python
|
|
255
|
+
# Save as Parquet (recommended for large datasets)
|
|
256
|
+
(
|
|
257
|
+
client.erc20.transfers("USDT")
|
|
258
|
+
.network("ETH")
|
|
259
|
+
.block_range(21000000, 21100000)
|
|
260
|
+
.as_file("transfers.parquet")
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
# Save as CSV
|
|
264
|
+
(
|
|
265
|
+
client.erc20.transfers("USDT")
|
|
266
|
+
.network("ETH")
|
|
267
|
+
.block_range(21000000, 21100000)
|
|
268
|
+
.as_file("transfers.csv")
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
# Save as JSON
|
|
272
|
+
(
|
|
273
|
+
client.erc20.transfers("USDT")
|
|
274
|
+
.network("ETH")
|
|
275
|
+
.block_range(21000000, 21010000)
|
|
276
|
+
.as_file("transfers.json")
|
|
277
|
+
)
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Return as Dictionary (JSON)
|
|
281
|
+
|
|
282
|
+
For small queries, you can get results as a list of dictionaries:
|
|
283
|
+
|
|
284
|
+
```python
|
|
285
|
+
transfers = (
|
|
286
|
+
client.erc20.transfers("USDT")
|
|
287
|
+
.network("ETH")
|
|
288
|
+
.block_range(21000000, 21010000)
|
|
289
|
+
.as_dict()
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
for transfer in transfers:
|
|
293
|
+
print(f"{transfer['sender']} -> {transfer['receiver']}: {transfer['amount']}")
|
|
294
|
+
```
|
|
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
|
+
|
|
298
|
+
### Async Usage
|
|
299
|
+
|
|
300
|
+
```python
|
|
301
|
+
import asyncio
|
|
302
|
+
from defistream import AsyncDeFiStream
|
|
303
|
+
|
|
304
|
+
async def main():
|
|
305
|
+
async with AsyncDeFiStream() as client:
|
|
306
|
+
df = await (
|
|
307
|
+
client.erc20.transfers("USDT")
|
|
308
|
+
.network("ETH")
|
|
309
|
+
.block_range(21000000, 21010000)
|
|
310
|
+
.as_df()
|
|
311
|
+
)
|
|
312
|
+
print(f"Found {len(df)} transfers")
|
|
313
|
+
|
|
314
|
+
asyncio.run(main())
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Configuration
|
|
318
|
+
|
|
319
|
+
### Environment Variables
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
export DEFISTREAM_API_KEY=dsk_your_api_key
|
|
323
|
+
export DEFISTREAM_BASE_URL=https://api.defistream.dev/v1 # optional
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
```python
|
|
327
|
+
from defistream import DeFiStream
|
|
328
|
+
|
|
329
|
+
# API key from environment
|
|
330
|
+
client = DeFiStream()
|
|
331
|
+
|
|
332
|
+
# Or explicit
|
|
333
|
+
client = DeFiStream(api_key="dsk_...", base_url="https://api.defistream.dev/v1")
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Timeout and Retries
|
|
337
|
+
|
|
338
|
+
```python
|
|
339
|
+
client = DeFiStream(
|
|
340
|
+
api_key="dsk_...",
|
|
341
|
+
timeout=60.0, # seconds
|
|
342
|
+
max_retries=3
|
|
343
|
+
)
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## Error Handling
|
|
347
|
+
|
|
348
|
+
```python
|
|
349
|
+
from defistream import DeFiStream
|
|
350
|
+
from defistream.exceptions import (
|
|
351
|
+
DeFiStreamError,
|
|
352
|
+
AuthenticationError,
|
|
353
|
+
QuotaExceededError,
|
|
354
|
+
RateLimitError,
|
|
355
|
+
ValidationError
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
client = DeFiStream()
|
|
359
|
+
|
|
360
|
+
try:
|
|
361
|
+
df = (
|
|
362
|
+
client.erc20.transfers("USDT")
|
|
363
|
+
.network("ETH")
|
|
364
|
+
.block_range(21000000, 21010000)
|
|
365
|
+
.as_df()
|
|
366
|
+
)
|
|
367
|
+
except AuthenticationError:
|
|
368
|
+
print("Invalid API key")
|
|
369
|
+
except QuotaExceededError as e:
|
|
370
|
+
print(f"Quota exceeded. Remaining: {e.remaining}")
|
|
371
|
+
except RateLimitError as e:
|
|
372
|
+
print(f"Rate limited. Retry after: {e.retry_after}s")
|
|
373
|
+
except ValidationError as e:
|
|
374
|
+
print(f"Invalid request: {e.message}")
|
|
375
|
+
except DeFiStreamError as e:
|
|
376
|
+
print(f"API error: {e}")
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## Response Headers
|
|
380
|
+
|
|
381
|
+
Access rate limit and quota information:
|
|
382
|
+
|
|
383
|
+
```python
|
|
384
|
+
df = (
|
|
385
|
+
client.erc20.transfers("USDT")
|
|
386
|
+
.network("ETH")
|
|
387
|
+
.block_range(21000000, 21010000)
|
|
388
|
+
.as_df()
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
# Access response metadata
|
|
392
|
+
print(f"Rate limit: {client.last_response.rate_limit}")
|
|
393
|
+
print(f"Remaining quota: {client.last_response.quota_remaining}")
|
|
394
|
+
print(f"Request cost: {client.last_response.request_cost}")
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
## Builder Methods Reference
|
|
398
|
+
|
|
399
|
+
### Common Methods (all protocols)
|
|
400
|
+
|
|
401
|
+
| Method | Description |
|
|
402
|
+
|--------|-------------|
|
|
403
|
+
| `.network(net)` | Set network (ETH, ARB, BASE, OP, POLYGON, etc.) |
|
|
404
|
+
| `.start_block(n)` | Set starting block number |
|
|
405
|
+
| `.end_block(n)` | Set ending block number |
|
|
406
|
+
| `.block_range(start, end)` | Set both start and end blocks |
|
|
407
|
+
| `.start_time(ts)` | Set starting time (ISO format or Unix timestamp) |
|
|
408
|
+
| `.end_time(ts)` | Set ending time (ISO format or Unix timestamp) |
|
|
409
|
+
| `.time_range(start, end)` | Set both start and end times |
|
|
410
|
+
| `.verbose()` | Include all metadata fields |
|
|
411
|
+
|
|
412
|
+
### Protocol-Specific Parameters
|
|
413
|
+
|
|
414
|
+
| Method | Protocols | Description |
|
|
415
|
+
|--------|-----------|-------------|
|
|
416
|
+
| `.token(symbol)` | ERC20 | Token symbol (USDT, USDC) or contract address (required) |
|
|
417
|
+
| `.sender(addr)` | ERC20, Native | Filter by sender address |
|
|
418
|
+
| `.receiver(addr)` | ERC20, Native | Filter by receiver address |
|
|
419
|
+
| `.min_amount(amt)` | ERC20, Native | Minimum transfer amount |
|
|
420
|
+
| `.max_amount(amt)` | ERC20, Native | Maximum transfer amount |
|
|
421
|
+
| `.eth_market_type(type)` | AAVE | Market type for ETH: 'Core', 'Prime', 'EtherFi' |
|
|
422
|
+
| `.symbol0(sym)` | Uniswap | First token symbol (required) |
|
|
423
|
+
| `.symbol1(sym)` | Uniswap | Second token symbol (required) |
|
|
424
|
+
| `.fee(tier)` | Uniswap | Fee tier: 100, 500, 3000, 10000 (required) |
|
|
425
|
+
|
|
426
|
+
### Terminal Methods
|
|
427
|
+
|
|
428
|
+
| Method | Description |
|
|
429
|
+
|--------|-------------|
|
|
430
|
+
| `.as_df()` | Execute and return pandas DataFrame |
|
|
431
|
+
| `.as_df("polars")` | Execute and return polars DataFrame |
|
|
432
|
+
| `.as_file(path)` | Execute and save to file (format from extension) |
|
|
433
|
+
| `.as_file(path, format="csv")` | Execute and save with explicit format |
|
|
434
|
+
| `.as_dict()` | Execute and return list of dicts (JSON, 10K block limit) |
|
|
435
|
+
|
|
436
|
+
## License
|
|
437
|
+
|
|
438
|
+
MIT License
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
defistream/__init__.py,sha256=duUlI1d-H7mP16D6dd0zbCslu45ARItE_pwQ5N7o05M,1089
|
|
2
|
+
defistream/client.py,sha256=Ku8ouDbM6Mx4lVmqvBwNvNt-h2FkvqauPMSjKyPkjU4,12717
|
|
3
|
+
defistream/exceptions.py,sha256=_GxZQ18_YvXFtmNHeddWV8fHPIllHgFeP7fP0CmHF1k,1492
|
|
4
|
+
defistream/models.py,sha256=Zw3DHAISxB6pivKybNzyHXR5IcRwvTZl23DHbjfyKwM,622
|
|
5
|
+
defistream/protocols.py,sha256=5_bYd46lDy-mK6LZ8sTGW0Z2IVH4g0cQ5rBbbOXsw0U,15368
|
|
6
|
+
defistream/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
defistream/query.py,sha256=sNn_0OzNDlsp4N74Grumsb08R5OFPPoppPok3vh8Y6Q,16775
|
|
8
|
+
defistream-1.0.6.dist-info/METADATA,sha256=2VBBk9BJNGQiGOyya3YCTB23rFTbes0UjNhma-4R4ig,10877
|
|
9
|
+
defistream-1.0.6.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
10
|
+
defistream-1.0.6.dist-info/licenses/LICENSE,sha256=72DWAof8dMePfFQmfaswClW5d-sE6k7p-7VpuSKLmU4,1067
|
|
11
|
+
defistream-1.0.6.dist-info/RECORD,,
|
|
@@ -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.
|