Skip to content

Instantly share code, notes, and snippets.

@jakerockland
Last active April 4, 2023 02:53
Show Gist options
  • Save jakerockland/6939284e2f7fc693d63010b206ac94e6 to your computer and use it in GitHub Desktop.
Save jakerockland/6939284e2f7fc693d63010b206ac94e6 to your computer and use it in GitHub Desktop.
Art Blocks Token Holders Subgraph Script
#!/usr/bin/env python3
########################################################################################
## This script provides an easy way to aggregate the token holders of Art Blocks
## projects.
##
## In this current example only project "0", Chromie Squiggles [1], is being queried for
## but you can readily change `project: "0"` to the project number of your choosing
## in the GraphQL query below.
##
## You can also remove `, project: "0"` from the query entirely, to pull data
## for all Art Blocks token holders.
##
## This data is pulled from the Art Blocks subgraph [2] and required Python 3
## and (optionally, but preferably) virtualenv [3].
##
## High level instructions to use this script:
## 1. Download this file from Github Gist, or copy and paste the contents into a
## new file named `ArtBlocksTokenHolders.py`. If you download the file, make
## sure to rename it to `ArtBlocksTokenHolders.py`.
## 2. Ensure that you have Python 3 and virtualenv [3] installed on your system,
## you can test this by running `python3 --version` and `virtualenv --version`
## from your terminal and ensuring a valid version string is output.
## 3. Ensure that you can navigate to the `ArtBlocksTokenHolders.py` file you
## downloaded/created via your terminal.
## 4. Make any modifications to the script (to query for a different project,
## for example) and save.
## 5. Run the script by running the commands in the instructions below from your
## terminal after having navigated to the directory containing your script
## (ex. by using the `cd` command in your terminal).
## 6. You should now have a `ArtBlocksTokenHolders.csv` file in the same
## directory that you ran the script in, which you can open with your favorite
## text editor or spreadsheet editor.
##
## To run this script do the following (after modifying as desired):
## `$ virtualenv -p python3 --no-site-packages ./venv`
## `$ source ./venv/bin/activate`
## `$ pip install requests`
## `$ python ArtBlocksTokenHolders.py`
##
## [1] https://artblocks.io/project/0
## [2] https://thegraph.com/explorer/subgraph/artblocks/art-blocks
## [3] https://pypi.org/project/virtualenv/
########################################################################################
from __future__ import print_function
import os
import requests
from requests.exceptions import HTTPError
import csv
import time
RESULTS_CSV = 'ArtBlocksTokenHolders.csv'
SUBGRAPH_ENDPOINT = 'https://api.thegraph.com/subgraphs/name/artblocks/art-blocks'
SUBGRAPH_QUERY= """
{{
tokens(first: {entries}, where: {{ id_gt: "{lastID}", project: "0" }}) {{
id
owner{{
id
}}
project {{
id
}}
}}
}}
"""
def getTokens(session, entries, lastID):
print(f'Retrieving next {entries} after item {lastID}.')
subgraphQuery = SUBGRAPH_QUERY.format(entries=entries, lastID=lastID)
try:
response = session.post(SUBGRAPH_ENDPOINT, json={'query': subgraphQuery})
response.raise_for_status()
return response.json()
except HTTPError as http_err:
print(f'HTTP error occurred: {http_err}')
return None
except Exception as err:
print(f'Other error occurred: {err}')
return None
def main():
session = requests.Session()
ownerToProjectsMap = dict()
entries = 1000
response = getTokens(session, entries, '')
while response:
tokens = response["data"]["tokens"]
if not tokens:
break
for token in tokens:
owner = token["owner"]["id"]
projectID = token["project"]["id"]
projects = ownerToProjectsMap.get(owner)
if projects is None:
projects = set()
projects.add(projectID)
ownerToProjectsMap[owner] = projects
time.sleep(1)
lastID = tokens[-1]["id"]
response = getTokens(session, entries, lastID)
with open(RESULTS_CSV, 'w') as f:
fieldnames = ['Owner', 'Projects', 'Total Projects Count']
writer = csv.DictWriter(f, quoting=csv.QUOTE_ALL, fieldnames=fieldnames)
writer.writeheader()
for owner, projects in ownerToProjectsMap.items():
writer.writerow({
'Owner': owner,
'Projects': sorted(projects),
'Total Projects Count': len(projects)
})
if __name__ == "__main__":
main()
@Heyotetsuo
Copy link

Heyotetsuo commented Jun 9, 2021

nice! i added command line arguments for convenience

> import sys
52a54,58
> if ( len(sys.argv) > 1 ):
>     PROJECT = sys.argv[1]
> else:
>     PROJECT = "0"
>
57c63
<   tokens(first: {entries}, where: {{ id_gt: "{lastID}", project: "0" }}) {{
---
>   tokens(first: {entries}, where: {{ id_gt: "{lastID}", project: "%s" }}) {{
67c73
< """
---
> """ % PROJECT```

so you can just do `python3 ArtBlocksTokenHolders.py [number]`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment