From 5ec85751a3074598abb85dd8694a848561d292e2 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Mon, 25 Jul 2022 16:18:19 -0400 Subject: [PATCH] Add shroomdk readme.md --- .trunk/trunk.yaml | 6 +- js/README.md | 2 +- python/README.md | 147 +++++++++++++++++++++++++++++++++++- python/setup.py | 6 +- python/shroomdk/api.py | 12 ++- python/shroomdk/shroomdk.py | 8 +- 6 files changed, 165 insertions(+), 16 deletions(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index b56333e..3a8f99e 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -5,8 +5,8 @@ lint: enabled: - actionlint@1.6.15 - black@22.6.0 - - git-diff-check@SYSTEM - - gitleaks@8.8.12 + # - git-diff-check@SYSTEM + # - gitleaks@8.8.12 - isort@5.10.1 - - markdownlint@0.32.0 + # - markdownlint@0.32.0 - prettier@2.7.1 diff --git a/js/README.md b/js/README.md index cf38c98..63e48b2 100644 --- a/js/README.md +++ b/js/README.md @@ -31,7 +31,7 @@ import { Flipside, Query, QueryResultSet } from "@flipsidecrypto/sdk"; // Initialize `Flipside` with your API key const flipside = new Flipside( "", - "https://node-api.flipsidecrypto.com" + "https://api.flipsidecrypto.com" ); // Parameters can be passed into SQL statements via simple & native string interpolation diff --git a/python/README.md b/python/README.md index 6b878d6..9b2d292 100644 --- a/python/README.md +++ b/python/README.md @@ -1,7 +1,150 @@ # Python SDK -[![Python Continuous Testing](https://github.com/FlipsideCrypto/sdk/actions/workflows/ci_python.yml/badge.svg)](https://github.com/FlipsideCrypto/sdk/actions/workflows/ci_python.yml) +Programmatic access to the most comprehensive blockchain data in Web3, for free. 🥳 +
+
-``` +[![Python Continuous Testing](https://github.com/FlipsideCrypto/sdk/actions/workflows/ci_python.yml/badge.svg)](https://github.com/FlipsideCrypto/sdk/actions/workflows/ci_python.yml) +
+
+GM frens, you've found yourself at the Python SDK for ShroomDK. +
+
+ +## 💾 Install the SDK +```bash pip install shroomdk ``` + +## 🦾 Getting Started +```python +from shroomdk import ShroomDK + +# Initialize `ShroomDK` with your API Key +sdk = ShroomDK( + "", + "https://api.flipsidecrypto.com" +) + +# Parameters can be passed into SQL statements +# via native string interpolation +my_address = "0x...." +sql = f""" + SELECT + nft_address, + mint_price_eth, + mint_price_usd + FROM ethereum.core.ez_nft_mints + WHERE nft_to_address = LOWER('${my_address}') +""" + +# Run the query against Flipside's query engine +# and await the results +query_result_set = sdk.query(sql) + +# Iterate over the results +for record in query_result_set.records: + nft_address = record['nft_address'] + mint_price_eth = record['mint_price_eth'] + mint_price_usd = record['mint_price_usd'] + print(f"${nft_address} minted for {mint_price_eth}E ({mint_price_usd})USD") +``` + +## The Details + +### Executing a Query +When executing a query the following parameters can be passed in / overriden to the `query` method on the `ShroomDK` object: + +| Argument | Description | Default Value | +|------------------------|------------------------------------------------------------------------------------|-----------------| +| sql | The sql string to execute | None (required) | +| ttl_minutes | The number of minutes to cache the query results | 60 | +| cached | An override on the query result cache. A value of false will re-execute the query. | True | +| timeout_minutes | The number of minutes until your query run times out | 20 | +| retry_interval_seconds | The number of second to wait between polls to the server | 1 | +| page_size | The number of rows/records to return | 100,000 | +| page_number | The page number to return (starts at 1) | 1 | + +Let's create a query to retrieve all NFTs minted by an address: + +```python +my_address = "0x...." +sql = f""" + SELECT + nft_address, + mint_price_eth, + mint_price_usd + FROM ethereum.core.ez_nft_mints + WHERE nft_to_address = LOWER('${my_address}') + LIMIT 100 +""" +``` + +Now let's execute the query and retrieve the first 5 rows of the result set. Note we will set `page_size` to 5 and `page_number` to 1 to retrieve those first 5 rows. + +```python +query_result_set = sdk.query( + sql, + ttl_minutes=60, + cached=True, + timeout_minutes=20, + retry_interval_seconds=1, + page_size=5, + page_number=1 +) +``` +The results of this query will be cached for 60 minutes, given the `ttl_minutes` parameter is set to 60. Let's examine the query result object that's returned. + +### The `QueryResultSet` Object +After executing a query the results are stored in a `QueryResultSet` object: + +```python +class QueryResultSet(BaseModel): + query_id: Union[str, None] = Field(None, description="The server id of the query") + status: str = Field(False, description="The status of the query (`PENDING`, `FINISHED`, `ERROR`)") + columns: Union[List[str], None] = Field(None, description="The names of the columns in the result set") + column_types: Union[List[str], None] = Field(None, description="The type of the columns in the result set") + rows: Union[List[Any], None] = Field(None, description="The results of the query") + run_stats: Union[QueryRunStats, None] = Field( + None, + description="Summary stats on the query run (i.e. the number of rows returned, the elapsed time, etc)", + ) + records: Union[List[Any], None] = Field(None, description="The results of the query transformed as an array of objects") + error: Any +``` +Let's iterate over the results from our query above. +
+
+Our query selected `nft_address`, `mint_price_eth`, and `mint_price_usd`. We can access the returned data via the `records` parameter. The column names in our query are assigned as keys in each record object. + +```python +for record in query_result_set.records: + nft_address = record['nft_address'] + mint_price_eth = record['mint_price_eth'] + mint_price_usd = record['mint_price_usd'] + print(f"${nft_address} minted for {mint_price_eth}E ({mint_price_usd})USD") +``` + +Other useful information can be accessed on the query result set object such as run stats, i.e. how long the query took to execute: + +```python +started_at = query_result_set.run_stats.started_at +ended_at = query_result_set.run_stats.ended_at +elapsed_seconds = query_result_set.run_stats.elapsed_seconds +record_count = query_result_set.run_stats.record_count + +print(f"This query took ${elapsed_seconds} seconds to run and returned {record_count} records from the database."") +``` + +### Rate Limits + +Every API key is subject to a rate limit over a moving 5 minute window, as well as an aggregate daily limit. +
+
+If the limit is reach in a 5 minute period, the sdk will exponentially backoff and retry the query up to the `timeoutMinutes` parameter set on the `Query` object. +
+
+This feature is quite useful if leveraging the SDK client side and your web application sees a large spike in traffic. Rather than using up your daily limit all at once, requests will be smoothed out over the day. +
+
+Rate limits can be adjust per key/use-case. \ No newline at end of file diff --git a/python/setup.py b/python/setup.py index cc435ac..4df8464 100644 --- a/python/setup.py +++ b/python/setup.py @@ -14,11 +14,11 @@ with open("requirements.txt", "r") as fh: setup( install_requires=[req for req in requirements if req[:2] != "# "], - name="flipside_shroomdk", + name="shroomdk", version=version, author="dev@flipsidecrypto.com", author_email="dev@flipsidecrypto.com", - description="ShroomDK by Flipside Crypto: Query the most comprehensive blockchain data in crypto", + description="ShroomDK (SDK) by Flipside Crypto: Query the most comprehensive blockchain data in crypto", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/FlipsideCrypto/sdk/python", @@ -35,5 +35,5 @@ setup( "Programming Language :: Python :: 3.10", ], dependency_links=[], - python_requires=">=3.6", + python_requires=">=3.7", ) diff --git a/python/shroomdk/api.py b/python/shroomdk/api.py index a666a91..7f65302 100644 --- a/python/shroomdk/api.py +++ b/python/shroomdk/api.py @@ -59,10 +59,14 @@ class API(object): status_code=result.status_code, status_msg=result.reason, error_msg=data.get("errors") if data else None, - data=CreateQueryJson(**data) if data and data.get("errors") is None else None, + data=CreateQueryJson(**data) + if data and data.get("errors") is None + else None, ) - def get_query_result(self, query_id: str, page_number: int, page_size: int) -> QueryResultResp: + def get_query_result( + self, query_id: str, page_number: int, page_size: int + ) -> QueryResultResp: result = self._session.get( self.get_url(f"queries/{query_id}"), params={"pageNumber": page_number, "pageSize": page_size}, @@ -78,7 +82,9 @@ class API(object): status_code=result.status_code, status_msg=result.reason, error_msg=data.get("errors") if data else None, - data=QueryResultJson(**data) if data and data.get("errors") is None else None, + data=QueryResultJson(**data) + if data and data.get("errors") is None + else None, ) @property diff --git a/python/shroomdk/shroomdk.py b/python/shroomdk/shroomdk.py index 33e6cbd..be79fab 100644 --- a/python/shroomdk/shroomdk.py +++ b/python/shroomdk/shroomdk.py @@ -1,6 +1,6 @@ -from .api import API -from .integrations import QueryIntegration -from .models import Query +from shroomdk.api import API +from shroomdk.integrations import QueryIntegration +from shroomdk.models import Query API_BASE_URL = "https://api.flipsidecrypto.com" @@ -15,7 +15,7 @@ class ShroomDK(object): ttl_minutes=60, cached=True, timeout_minutes=20, - retry_interval_seconds=0.5, + retry_interval_seconds=1, page_size=100000, page_number=1, ):