├── .github └── workflows │ ├── release-github.yml │ ├── release-python.yml │ └── tests.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── MANIFEST.in ├── README.md ├── deficrawler ├── __init__.py ├── api_calls.py ├── block.py ├── config │ ├── __init__.py │ ├── aave-2.json │ ├── aave-3.json │ ├── balancer-1.json │ ├── balancer-2.json │ ├── bancor-1.json │ ├── block-1.json │ ├── chainlink-1.json │ ├── compound-2.json │ ├── cream-2-arbitrum.json │ ├── cream-2-avalanche.json │ ├── cream-2-fantom.json │ ├── cream-2.json │ ├── dodoex-2.json │ ├── global.json │ ├── kashi-1.json │ ├── kyber-1.json │ ├── pancakeswap-1.json │ ├── pancakeswap-2.json │ ├── pangolin-1.json │ ├── protocol_template.json │ ├── quickswap-1.json │ ├── scream-1.json │ ├── sushiswap-1-ethereum.json │ ├── sushiswap-1.json │ ├── traderjoe-1.json │ ├── ubeswap-1.json │ ├── uniswap-2.json │ ├── uniswap-3.json │ └── venus-1.json ├── dex.py ├── lending.py ├── mappers.py ├── oracle.py ├── protocol_base.py ├── querys.py ├── transformer.py └── utils.py ├── docs ├── entities │ ├── Amm.md │ ├── Lending.md │ └── Prices.md └── examples.py ├── setup.py └── tests ├── int ├── test_blocks.py ├── test_borrows.py ├── test_burn.py ├── test_deposits.py ├── test_flashloans.py ├── test_liquidations.py ├── test_mint.py ├── test_prices.py ├── test_redeem.py ├── test_repays.py ├── test_swaps.py └── test_volume.py └── unit ├── test_dex.py ├── test_lending.py ├── test_protocol_base.py ├── test_transformer.py └── test_utils.py /.github/workflows/release-github.yml: -------------------------------------------------------------------------------- 1 | name: Github Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*.*' 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v2 14 | - name: Release 15 | uses: softprops/action-gh-release@v1 16 | if: startsWith(github.ref, 'refs/tags/') 17 | with: 18 | files: | 19 | target/*.jar 20 | env: 21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 22 | -------------------------------------------------------------------------------- /.github/workflows/release-python.yml: -------------------------------------------------------------------------------- 1 | # This workflows will upload a Python Package using Twine when a release is created 2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries 3 | 4 | name: Upload Python Package 5 | 6 | on: 7 | push: 8 | tags: 9 | - 'v*.*' 10 | 11 | jobs: 12 | deploy: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Set up Python 19 | uses: actions/setup-python@v1 20 | with: 21 | python-version: '3.x' 22 | - name: Install dependencies 23 | run: | 24 | python -m pip install --upgrade pip 25 | pip install setuptools wheel twine 26 | - name: Build and publish 27 | env: 28 | TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} 29 | TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} 30 | run: | 31 | python setup.py sdist bdist_wheel 32 | twine upload dist/* 33 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | pull_request: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | tests: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Set up Python 17 | uses: actions/setup-python@v1 18 | with: 19 | python-version: '3.x' 20 | - name: Install dependencies 21 | run: | 22 | python -m pip install --upgrade pip 23 | pip install pytest 24 | pip install -e . 25 | - name: Tests 26 | run: | 27 | python -m pytest -v 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include CHANGELOG.md 2 | include LICENSE 3 | include README.md 4 | 5 | recursive-include tests * 6 | recursive-exclude * __pycache__ 7 | 8 | global-include *.json 9 | 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![banner](https://raw.githubusercontent.com/keyko-io/assets/master/images/logo/small/keyko_logo@2x-100.jpg)](https://keyko.io) 2 | 3 | # DeFi Crawler Python library 4 | > [keyko.io](https://keyko.io) 5 | --- 6 | 7 | ## Table of Contents 8 | 9 | - [Features](#features) 10 | - [Prerequisites](#prerequisites) 11 | - [Quick-start](#quick-start) 12 | - [Usage](#usage) 13 | - [Supported protocols](#supported-protocols) 14 | - [Testing](#testing) 15 | - [Contributions](#contributions) 16 | - [License](#license) 17 | 18 | --- 19 | 20 | ## Features 21 | 22 | This library allows to get DeFi data from several protocols in a structured and standard way. This data comes from different subgraphs displayed in The Graph protocol 23 | 24 | ## Prerequisites 25 | 26 | Python 3.6 27 | 28 | ## Quick-start 29 | 30 | ``` 31 | pip install deficrawler 32 | ``` 33 | 34 | ### Usage 35 | 36 | To get data from a protocol, it's needed to create an instance of the protocol with the name, version and blockchain where the protocols exists, the supported protocols can be found in [supported protocols](#supported-protocols) section. And the entities for the protocols with the field types in the [entities](#https://github.com/keyko-io/defi-crawler-py/tree/main/docs/entities) folder 37 | 38 | To get data from Lending protocols 39 | 40 | ```python 41 | # Instanciate the protocol with the name, version and chain 42 | from deficrawler import Lending 43 | 44 | aave = Lending(protocol="Aave", chain="Ethereum", version=2) 45 | aave_polygon = Lending(protocol="Aave", chain="Polygon", version=2) 46 | compound = Lending(protocol="Compound", chain="Ethereum", version=2) 47 | cream = Lending(protocol="Cream", chain="Ethereum", version=2) 48 | cream_bsc = Lending(protocol="Cream", chain="bsc", version=2) 49 | 50 | # Not all the protocols has the same available events to get data, to know which entities are supported for each protocol: 51 | aave.supported_entities() 52 | uniswap.suported_entities() 53 | 54 | ## For each different entity, data can be retrieved in a specific time range. 55 | compound.get_data_from_date_range(start_date, end_date, "borrow") 56 | 57 | # To get the all the users of a protocol 58 | cream_bsc.get_all_users() 59 | 60 | # And the user positions 61 | cream_bsc.get_all_users(user) 62 | 63 | ``` 64 | 65 | To get data from Dex protocols 66 | 67 | ```python 68 | # Instanciate the protocol with the name, version and chain 69 | from deficrawler import Dex 70 | 71 | uniswap = Dex(protocol="Uniswap", chain="Ethereum", version=2) 72 | balancer = Dex(protocol="Balancer", chain="Ethereum", version=1) 73 | bancor = Dex("Bancor", chain="Ethereum", version=1) 74 | shushi = Dex("SushiSwap", chain="Ethereum", version=1) 75 | 76 | # Not all the protocols has the same available events to get data, to know which entities are supported for each protocol: 77 | uniswap.supported_entities() 78 | balancer.suported_entities() 79 | 80 | ## For each different entity, data can be retrieved in a specific time range. 81 | uniswap.get_data_from_date_range(start_date_amm, end_date_amm, "swap") 82 | 83 | # To get the all the pools of a protocol 84 | uniswap.get_all_pools() 85 | 86 | ``` 87 | 88 | To get prices from the oracles it's needed to instanciate an oracle object and call the functions. 89 | 90 | ```python 91 | # Instanciate the oracle with the name, version and chain 92 | from deficrawler import Oracle 93 | 94 | chainlink = Oracle(protocol="chainlink", version=1, chain="Ethereum") 95 | 96 | #Get all the available pairs to get the data 97 | chainlink.get_all_pairs() 98 | 99 | #Get the price for a specific pair in a time range 100 | chainlink.get_price_from_date_range(from_date=start_date, to_date=end_date, pair="ETH/USD") 101 | 102 | ``` 103 | 104 | ### Supported-protocols 105 | 106 | #### Protocols 107 | 108 | Name | Type | Version | Chain 109 | --------|-------|---------|------- 110 | Aave | Lending | 2 | Ethereum 111 | Aave | Lending | 2 | Polygon 112 | Aave | Lending | 2 | Avalanche 113 | Compound | Lending | 2 | Ethereum 114 | Cream | Lending | 2 | Ethereum 115 | Cream | Lending | 2 | BSC 116 | Cream | Lending | 2 | Polygon 117 | Cream | Lending | 2 | Arbitrum 118 | Cream | Lending | 2 | Avalance 119 | Cream | Lending | 2 | Fantom 120 | Kashi | Lending | 1 | Ethereum 121 | Kashi | Lending | 1 | Polygon 122 | Kashi | Lending | 1 | xDai 123 | Kashi | Lending | 1 | fantom 124 | Uniswap | Dexes | 2 | Ethereum 125 | Uniswap | Dexes | 3 | Ethereum 126 | Uniswap | Dexes | 3 | Optimism 127 | Balancer | Dexes | 2 | Ethereum 128 | Balancer | Dexes | 2 | Arbitrum 129 | Balancer | Dexes | 2 | Polygon 130 | Bancor | Dexes | 1 | Ethereum 131 | SushiSwap | Dexes | 1 | Ethereum 132 | SushiSwap | Dexes | 1 | BSC 133 | SushiSwap | Dexes | 1 | Polygon 134 | SushiSwap | Dexes | 1 | Fantom 135 | SushiSwap | Dexes | 1 | Celo 136 | Dodoex | Dexes | 2 | Ethereum 137 | Dodoex | Dexes | 2 | Polygon 138 | Dodoex | Dexes | 2 | BSC 139 | Dodoex | Dexes | 2 | Arbitrum 140 | Ubeswap | Dexes | 1 | Celo 141 | Pancakeswap | Dexes | 2 | BSC 142 | Pangolin | Dexes | 1 | Avalanche 143 | Traderjoe | Dexes | 1 | Avalanche 144 | 145 | 146 | 147 | 148 | #### Oracles 149 | Name | Type | Version | Chain 150 | --------|-------|---------|------- 151 | Chainlink | Oracle | 1 | Ethereum 152 | 153 | #### Testing 154 | 155 | Tests are creatd using Pytest library. To run the tests 156 | 157 | pytest -v 158 | 159 | 160 | #### Examples 161 | 162 | To run the examples run 163 | 164 | python3 docs/examples.py 165 | 166 | 167 | ### Contributions 168 | If you want to add a new protocol to be supported or a new entity to retrive data, create a PR with the new configuration of the protocol and the unit/integration tests of this new feature. 169 | 170 | To add a new protocol, create a new json config file in the config folder, with the struture `protocolname-version.json`. 171 | Inside this configuration file must be the following sections: 172 | ##### Protocol 173 | This section specifies the global configuration of the protocol. The required fields are 174 | - **Name:** Protocol name. 175 | - **Type:** Protocol type (Borrowing lending) 176 | - **Version:** Version of the protcol 177 | - **Enpoint:** Subgrapn endpoint to send the http request to get the data. If the protocols exists on more than one chain, several enpoints can be provided 178 | 179 | **Example** 180 | ````json 181 | "protocol": { 182 | "name": "AAVE", 183 | "type": "Lending", 184 | "version": 2, 185 | "endpoint": { 186 | "ethereum": "https://api.thegraph.com/subgraphs/name/aave/protocol-v2", 187 | "polygon": "https://api.thegraph.com/subgraphs/name/aave/aave-v2-matic" 188 | } 189 | } 190 | ```` 191 | 192 | 193 | After this section the supported entities should be specified. Each entity has three different sections inside of them. 194 | - **Entity:** The entity contains the fields to create a common entity from a shared type of event of different protocols (borrow, swap, deposit...). The entity starts with the name that will be applied to this specific event across all the protocols. Then should be a field for each attribute that will be contained in the entity, and each field shoud have an array, with the path to find this element in the corresponding subpgraph, these fields will be used to create the query. As example for borrow entity in Aave: 195 | ```` 196 | "borrow": { 197 | "attributes": { 198 | "tx_id":[ 199 | "id" 200 | ], 201 | "user": [ 202 | "user", 203 | "id" 204 | ], 205 | "token": [ 206 | "reserve", 207 | "symbol" 208 | ], 209 | "amount": [ 210 | "amount" 211 | ], 212 | "timestamp": [ 213 | "timestamp" 214 | ] 215 | } 216 | - **Query:**: Each query in each protocol can be named different, to allow create the query dynamically, the query name should be specified and the field to order by if will be more that one batch to retrive. In this section also can be specified, additional fields to get data from the subgraph that will be needed to apply transformations, but will not be part of the output itself. As example for Aave we need to get the decimals for the token to divide the amount, but the decimals are not part of the entity. As example 217 | ```` 218 | "query": { 219 | "extra_fields": { 220 | "decimals": [ 221 | "reserve", 222 | "decimals" 223 | ] 224 | }, 225 | "name": "borrows", 226 | "params": { 227 | "orderBy": "timestamp" 228 | } 229 | } 230 | - **Tranformations:** This section specified the transformations that should be applied to the fields (if any transformation should be applied). Here we can specify the field of the common entity (the output) that needs to be transform, and the function that will be applied. This funtion will be call dinamically in the transformation phase. As example: 231 | ```` 232 | "transformations": { 233 | "amount": "decimals", 234 | "tx_id":"tx_id_colon" 235 | } 236 | ```` 237 | 238 | ## License 239 | 240 | ```text 241 | Copyright 2020 Keyko GmbH. 242 | 243 | Licensed under the Apache License, Version 2.0 (the "License"); 244 | you may not use this file except in compliance with the License. 245 | You may obtain a copy of the License at 246 | 247 | http://www.apache.org/licenses/LICENSE-2.0 248 | 249 | Unless required by applicable law or agreed to in writing, software 250 | distributed under the License is distributed on an "AS IS" BASIS, 251 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 252 | See the License for the specific language governing permissions and 253 | limitations under the License. 254 | ``` 255 | -------------------------------------------------------------------------------- /deficrawler/__init__.py: -------------------------------------------------------------------------------- 1 | from deficrawler.lending import Lending 2 | from deficrawler.dex import Dex 3 | from deficrawler.oracle import Oracle 4 | from deficrawler.block import Block 5 | 6 | -------------------------------------------------------------------------------- /deficrawler/api_calls.py: -------------------------------------------------------------------------------- 1 | from deficrawler.utils import get_attributes, get_filters, filter_method 2 | 3 | import requests 4 | import json 5 | from retry import retry 6 | 7 | 8 | def get_data_from(query_input, entity, from_timestamp, to_timestamp, mappings_file, endpoint, aditional_filters=""): 9 | """ 10 | Gets all the existing data from the subgraph at the given time range. 11 | One or mor filters can be passed as parameters and will be applied in the where clause 12 | """ 13 | are_data = True 14 | json_records = [] 15 | iteration_timestamp = from_timestamp 16 | 17 | entity_name = mappings_file['entities'][entity]['query']['name'] 18 | order_by = mappings_file['entities'][entity]['query']['params']['orderBy'] 19 | attributes = get_attributes(entity, mappings_file) 20 | filters_str = get_filters(aditional_filters) 21 | 22 | while are_data: 23 | query = query_input.format( 24 | entity_name=entity_name, 25 | order_by=order_by, 26 | from_timestamp=iteration_timestamp, 27 | to_timestamp=to_timestamp, 28 | attributes=attributes, 29 | aditional_filters=filters_str 30 | ) 31 | 32 | json_data = call_api(endpoint=endpoint, query=query) 33 | 34 | response_lenght = len(json_data['data'][entity_name]) 35 | if (response_lenght > 0): 36 | list_data = json_data['data'][entity_name] 37 | iteration_timestamp = json_data['data'][entity_name][response_lenght - 1][order_by] 38 | 39 | json_records = [*json_records, *list_data] 40 | else: 41 | are_data = False 42 | 43 | return json_records 44 | 45 | 46 | def get_data_parameter(query_input, entity, mappings_file, endpoint): 47 | """ 48 | Gets all the existing data for the given entity. 49 | If this entity has some filter, in the config file, the query will apply 50 | this filter 51 | """ 52 | are_data = True 53 | json_records = [] 54 | 55 | entity_name = mappings_file['entities'][entity]['query']['name'] 56 | order_by = mappings_file['entities'][entity]['query']['params']['orderBy'] 57 | filter_value = mappings_file['entities'][entity]['query']['params']['initial_value'] 58 | attributes = get_attributes(entity, mappings_file) 59 | 60 | while are_data: 61 | query = query_input.format( 62 | entity_name=entity_name, 63 | order_by=order_by, 64 | filter_value=filter_value, 65 | attributes=attributes 66 | ) 67 | 68 | json_data = call_api(endpoint=endpoint, query=query) 69 | 70 | response_lenght = len(json_data['data'][entity_name]) 71 | if (response_lenght > 0): 72 | list_data = json_data['data'][entity_name] 73 | filter_value = json_data['data'][entity_name][response_lenght - 1][order_by] 74 | 75 | json_records = [*json_records, *list_data] 76 | else: 77 | are_data = False 78 | 79 | return json_records 80 | 81 | 82 | def get_data_filtered(query_input, entity, mappings_file, endpoint, filters): 83 | """ 84 | Gets all the existing data from the subgraph applying the given filters 85 | """ 86 | entity_name = mappings_file['entities'][entity]['query']['name'] 87 | filters_str = get_filters(filters) 88 | 89 | attributes = get_attributes(entity, mappings_file) 90 | 91 | query = query_input.format( 92 | entity_name=entity_name, 93 | filters=filters_str, 94 | attributes=attributes 95 | ) 96 | 97 | json_data = call_api(endpoint=endpoint, query=query) 98 | json_records = [] 99 | 100 | response_lenght = len(json_data['data'][entity_name]) 101 | if (response_lenght > 0): 102 | list_data = json_data['data'][entity_name] 103 | 104 | json_records = [*list_data] 105 | 106 | return json_records 107 | 108 | 109 | def get_first_element(query_input, entity, mappings_file, endpoint, timestamp, aditional_filters, block=None): 110 | """ 111 | Gets first existing data from the subgraph applying the given filters 112 | """ 113 | entity_name = mappings_file['entities'][entity]['query']['name'] 114 | filters_str = get_filters(aditional_filters) 115 | order_by = mappings_file['entities'][entity]['query']['params']['orderBy'] 116 | attributes = get_attributes(entity, mappings_file) 117 | params = filter_method(block=block, 118 | order_by_filter=order_by, 119 | lte='_lte:', 120 | timestamp=timestamp) 121 | 122 | query = query_input.format( 123 | entity_name=entity_name, 124 | order_by=order_by, 125 | order_by_filter=params['order_by_filter'], 126 | aditional_filters=filters_str, 127 | attributes=attributes, 128 | timestamp=params['timestamp'], 129 | lte=params['lte'], 130 | block=params['block'] 131 | ) 132 | 133 | json_data = call_api(endpoint=endpoint, query=query) 134 | json_records = [] 135 | 136 | response_lenght = len(json_data['data'][entity_name]) 137 | if (response_lenght > 0): 138 | list_data = json_data['data'][entity_name] 139 | 140 | json_records = [*list_data] 141 | 142 | return json_records 143 | 144 | @retry(Exception, tries=3, delay=2) 145 | def call_api(endpoint, query): 146 | """ 147 | Returns the data from the api, if there is any error throws 148 | """ 149 | response = requests.post(endpoint, json={'query': query}) 150 | json_data = json.loads(response.text) 151 | if 'errors' in json_data: 152 | raise Exception( 153 | 'There was an error getting the data from TheGraph' + json.dumps(json_data)) 154 | 155 | return json_data 156 | -------------------------------------------------------------------------------- /deficrawler/block.py: -------------------------------------------------------------------------------- 1 | from deficrawler.protocol_base import ProtocolBase 2 | 3 | 4 | class Block(ProtocolBase): 5 | """ 6 | Class to get data for the blockchain blocks 7 | """ 8 | 9 | def __init__(self, protocol, chain, version): 10 | super().__init__( 11 | protocol=protocol, 12 | chain=chain, 13 | version=version 14 | ) 15 | self.protocol_type = "blocks" 16 | 17 | def get_block_at_timestamp(self, timestamp): 18 | """ 19 | Gets the block number for a specific timestamp 20 | """ 21 | 22 | config = super().get_protocol_config('block') 23 | 24 | response_data = super().query_first_element( 25 | entity='block', 26 | timestamp=timestamp, 27 | aditional_filters='' 28 | ) 29 | 30 | return super().map_data( 31 | response_data=response_data, 32 | config=config 33 | ) 34 | 35 | def get_block_info(self, block_number): 36 | """ 37 | Gets the block information related to a block number 38 | """ 39 | 40 | config = super().get_protocol_config('block_info') 41 | 42 | block_name = self.mappings_file['entities']['block_info']['query']['params']['number'] 43 | 44 | response_data = super().query_data_filtered( 45 | filters={block_name: str(block_number)}, 46 | entity='block_info' 47 | ) 48 | 49 | return super().map_data( 50 | response_data=response_data, 51 | config=config 52 | ) 53 | 54 | def supported_entities(self): 55 | """ 56 | Returns the supported entities for the protocol 57 | """ 58 | return super().supported_entities(self.protocol_type) 59 | -------------------------------------------------------------------------------- /deficrawler/config/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keyko-io/defi-crawler-py/28096033f2182487e4daecdc4c1b124a964100f8/deficrawler/config/__init__.py -------------------------------------------------------------------------------- /deficrawler/config/aave-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "AAVE", 4 | "type": "Lending", 5 | "version": 2, 6 | "chain": "Ethereum", 7 | "endpoint": { 8 | "ethereum": "https://api.thegraph.com/subgraphs/name/aave/protocol-v2", 9 | "polygon": "https://api.thegraph.com/subgraphs/name/aave/aave-v2-matic", 10 | "avalanche": "https://api.thegraph.com/subgraphs/name/aave/protocol-v2-avalanche" 11 | } 12 | }, 13 | "entities": { 14 | "borrow": { 15 | "attributes": { 16 | "tx_id": [ 17 | "id" 18 | ], 19 | "user": [ 20 | "user", 21 | "id" 22 | ], 23 | "token": [ 24 | "reserve", 25 | "symbol" 26 | ], 27 | "amount": [ 28 | "amount" 29 | ], 30 | "timestamp": [ 31 | "timestamp" 32 | ] 33 | }, 34 | "query": { 35 | "extra_fields": { 36 | "decimals": [ 37 | "reserve", 38 | "decimals" 39 | ] 40 | }, 41 | "name": "borrows", 42 | "params": { 43 | "orderBy": "timestamp", 44 | "user": "user" 45 | } 46 | }, 47 | "transformations": { 48 | "amount": "decimals", 49 | "tx_id": "tx_id_colon" 50 | } 51 | }, 52 | "deposit": { 53 | "attributes": { 54 | "tx_id": [ 55 | "id" 56 | ], 57 | "user": [ 58 | "user", 59 | "id" 60 | ], 61 | "token": [ 62 | "reserve", 63 | "symbol" 64 | ], 65 | "amount": [ 66 | "amount" 67 | ], 68 | "timestamp": [ 69 | "timestamp" 70 | ] 71 | }, 72 | "query": { 73 | "extra_fields": { 74 | "decimals": [ 75 | "reserve", 76 | "decimals" 77 | ] 78 | }, 79 | "name": "deposits", 80 | "params": { 81 | "orderBy": "timestamp", 82 | "user": "user" 83 | } 84 | }, 85 | "transformations": { 86 | "amount": "decimals", 87 | "tx_id": "tx_id_colon" 88 | } 89 | }, 90 | "liquidation": { 91 | "attributes": { 92 | "tx_id": [ 93 | "id" 94 | ], 95 | "user": [ 96 | "user", 97 | "id" 98 | ], 99 | "token_principal": [ 100 | "principalReserve", 101 | "symbol" 102 | ], 103 | "token_collateral": [ 104 | "collateralReserve", 105 | "symbol" 106 | ], 107 | "amount_principal": [ 108 | "principalAmount" 109 | ], 110 | "amount_collateral": [ 111 | "collateralAmount" 112 | ], 113 | "liquidator": [ 114 | "liquidator" 115 | ], 116 | "timestamp": [ 117 | "timestamp" 118 | ] 119 | }, 120 | "query": { 121 | "extra_fields": { 122 | "principal_decimals": [ 123 | "principalReserve", 124 | "decimals" 125 | ], 126 | "collateral_decimals": [ 127 | "collateralReserve", 128 | "decimals" 129 | ] 130 | }, 131 | "name": "liquidationCalls", 132 | "params": { 133 | "orderBy": "timestamp", 134 | "user": "user" 135 | } 136 | }, 137 | "transformations": { 138 | "amount_principal": "principal_decimals", 139 | "amount_collateral": "collateral_decimals", 140 | "tx_id": "tx_id_colon" 141 | } 142 | }, 143 | "repay": { 144 | "attributes": { 145 | "tx_id": [ 146 | "id" 147 | ], 148 | "user": [ 149 | "user", 150 | "id" 151 | ], 152 | "token": [ 153 | "reserve", 154 | "symbol" 155 | ], 156 | "amount": [ 157 | "amount" 158 | ], 159 | "timestamp": [ 160 | "timestamp" 161 | ] 162 | }, 163 | "query": { 164 | "name": "repays", 165 | "extra_fields": { 166 | "decimals": [ 167 | "reserve", 168 | "decimals" 169 | ] 170 | }, 171 | "params": { 172 | "orderBy": "timestamp", 173 | "user": "user" 174 | } 175 | }, 176 | "transformations": { 177 | "amount": "decimals", 178 | "tx_id": "tx_id_colon" 179 | } 180 | }, 181 | "redeem": { 182 | "attributes": { 183 | "tx_id": [ 184 | "id" 185 | ], 186 | "user": [ 187 | "user", 188 | "id" 189 | ], 190 | "token": [ 191 | "reserve", 192 | "symbol" 193 | ], 194 | "amount": [ 195 | "amount" 196 | ], 197 | "timestamp": [ 198 | "timestamp" 199 | ] 200 | }, 201 | "query": { 202 | "extra_fields": { 203 | "decimals": [ 204 | "reserve", 205 | "decimals" 206 | ] 207 | }, 208 | "name": "redeemUnderlyings", 209 | "params": { 210 | "orderBy": "timestamp", 211 | "user": "user" 212 | } 213 | }, 214 | "transformations": { 215 | "amount": "decimals", 216 | "tx_id": "tx_id_colon" 217 | } 218 | }, 219 | "flashloans": { 220 | "attributes": { 221 | "tx_id": [ 222 | "id" 223 | ], 224 | "user": [ 225 | "initiator", 226 | "id" 227 | ], 228 | "token": [ 229 | "reserve", 230 | "symbol" 231 | ], 232 | "amount": [ 233 | "amount" 234 | ], 235 | "timestamp": [ 236 | "timestamp" 237 | ] 238 | }, 239 | "query": { 240 | "name": "flashLoans", 241 | "extra_fields": { 242 | "decimals": [ 243 | "reserve", 244 | "decimals" 245 | ] 246 | }, 247 | "params": { 248 | "orderBy": "timestamp", 249 | "user": "initiator" 250 | } 251 | }, 252 | "transformations": { 253 | "amount": "decimals", 254 | "tx_id": "tx_id_colon" 255 | } 256 | }, 257 | "rates": { 258 | "attributes": { 259 | "token": [ 260 | "reserve", 261 | "symbol" 262 | ], 263 | "variable_borrow_rate": [ 264 | "variableBorrowRate" 265 | ], 266 | "stable_borrow_rate": [ 267 | "stableBorrowRate" 268 | ], 269 | "supply_rate": [ 270 | "liquidityRate" 271 | ], 272 | "timestamp": [ 273 | "timestamp" 274 | ] 275 | }, 276 | "query": { 277 | "name": "reserveParamsHistoryItems", 278 | "extra_fields": { 279 | "decimals": [ 280 | "reserve", 281 | "decimals" 282 | ] 283 | }, 284 | "params": { 285 | "orderBy": "timestamp", 286 | "asset": "reserve" 287 | } 288 | }, 289 | "transformations": { 290 | "variable_borrow_rate": "rates_units_aave", 291 | "stable_borrow_rate": "rates_units_aave", 292 | "supply_rate": "rates_units_aave" 293 | } 294 | }, 295 | "token": { 296 | "attributes": { 297 | "id": [ 298 | "id" 299 | ], 300 | "symbol": [ 301 | "symbol" 302 | ] 303 | }, 304 | "query": { 305 | "name": "reserves", 306 | "extra_fields": {}, 307 | "params": { 308 | "orderBy": "id", 309 | "initial_value": "0" 310 | } 311 | }, 312 | "transformations": {} 313 | }, 314 | "user": { 315 | "attributes": { 316 | "user_id": [ 317 | "id" 318 | ], 319 | "active_loans": [ 320 | "borrowedReservesCount" 321 | ], 322 | "liquidations_count": [ 323 | "liquidationCallHistory", 324 | "id" 325 | ] 326 | }, 327 | "query": { 328 | "name": "users", 329 | "extra_fields": {}, 330 | "params": { 331 | "orderBy": "id", 332 | "initial_value": "0" 333 | } 334 | }, 335 | "transformations": { 336 | "liquidations_count": "array_length" 337 | } 338 | }, 339 | "user_position": { 340 | "attributes": { 341 | "user_id": [ 342 | "user", 343 | "id" 344 | ], 345 | "symbol": [ 346 | "reserve", 347 | "symbol" 348 | ], 349 | "debt_amount": [ 350 | "currentTotalDebt" 351 | ], 352 | "collateral_amount": [ 353 | "currentATokenBalance" 354 | ] 355 | }, 356 | "query": { 357 | "name": "userReserves", 358 | "extra_fields": { 359 | "decimals": [ 360 | "reserve", 361 | "decimals" 362 | ] 363 | }, 364 | "params": { 365 | "user": "user" 366 | } 367 | }, 368 | "transformations": { 369 | "collateral_amount": "decimals", 370 | "debt_amount": "decimals" 371 | } 372 | }, 373 | "prices": { 374 | "attributes": { 375 | "id": [ 376 | "reserve", 377 | "underlyingAsset" 378 | ], 379 | "symbol": [ 380 | "reserve", 381 | "symbol" 382 | ], 383 | "underlyingAsset": [ 384 | "reserve", 385 | "symbol" 386 | ], 387 | "priceInETH": [ 388 | "priceInEth" 389 | ], 390 | "priceInUsd": [ 391 | "priceInUsd" 392 | ], 393 | "exchangeRate": [ 394 | "priceInUsd" 395 | ], 396 | "timestamp": [ 397 | "timestamp" 398 | ] 399 | }, 400 | "query": { 401 | "name": "reserveParamsHistoryItems", 402 | "extra_fields": { 403 | }, 404 | "params": { 405 | "orderBy": "timestamp" 406 | } 407 | }, 408 | "transformations": { 409 | "exchangeRate": "exchange_rate_one" 410 | } 411 | } 412 | } 413 | } -------------------------------------------------------------------------------- /deficrawler/config/balancer-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Balancer", 4 | "type": "Balancer", 5 | "version": 1, 6 | "chain": "Ethereum", 7 | "endpoint": { 8 | "ethereum": "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer" 9 | } 10 | }, 11 | "entities": { 12 | "swap": { 13 | "attributes": { 14 | "user": [ 15 | "userAddress", 16 | "id" 17 | ], 18 | "tx_id": [ 19 | "id" 20 | ], 21 | "from_token": [ 22 | "tokenInSym" 23 | ], 24 | "to_token": [ 25 | "tokenOutSym" 26 | ], 27 | "from_token_amount": [ 28 | "tokenAmountIn" 29 | ], 30 | "to_token_amount": [ 31 | "tokenAmountOut" 32 | ], 33 | "pool":[ 34 | "poolAddress", 35 | "id" 36 | ], 37 | "timestamp": [ 38 | "timestamp" 39 | ] 40 | }, 41 | "query": { 42 | "name": "swaps", 43 | "extra_fields": {}, 44 | "params": { 45 | "orderBy": "timestamp", 46 | "pool": "poolAddress" 47 | } 48 | }, 49 | "transformations": {} 50 | }, 51 | "pool": { 52 | "attributes": { 53 | "id": [ 54 | "id" 55 | ], 56 | "pool_tokens": [ 57 | "tokens", 58 | "symbol" 59 | ] 60 | }, 61 | "query": { 62 | "name": "pools", 63 | "extra_fields": {}, 64 | "params": { 65 | "orderBy": "id", 66 | "initial_value": "0" 67 | } 68 | }, 69 | "transformations": { 70 | "pool_tokens": "concat_list_symbols" 71 | } 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /deficrawler/config/balancer-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Balancer", 4 | "type": "Balancer", 5 | "version": 2, 6 | "chain": "Ethereum", 7 | "endpoint": { 8 | "ethereum": "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-v2", 9 | "polygon": "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-polygon-v2", 10 | "arbitrum": "https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-arbitrum-v2" 11 | } 12 | }, 13 | "entities": { 14 | "swap": { 15 | "attributes": { 16 | "user": [ 17 | "userAddress", 18 | "id" 19 | ], 20 | "tx_id": [ 21 | "id" 22 | ], 23 | "from_token": [ 24 | "tokenInSym" 25 | ], 26 | "to_token": [ 27 | "tokenOutSym" 28 | ], 29 | "from_token_amount": [ 30 | "tokenAmountIn" 31 | ], 32 | "to_token_amount": [ 33 | "tokenAmountOut" 34 | ], 35 | "pool": [ 36 | "poolId", 37 | "address" 38 | ], 39 | "amount_usd": [ 40 | "id" 41 | ], 42 | "timestamp": [ 43 | "timestamp" 44 | ] 45 | }, 46 | "query": { 47 | "name": "swaps", 48 | "extra_fields": {}, 49 | "params": { 50 | "orderBy": "timestamp", 51 | "pool": "poolAddress" 52 | } 53 | }, 54 | "transformations": { 55 | "amount_usd": "na" 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /deficrawler/config/bancor-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Bancor", 4 | "type": "Bancor", 5 | "version": 1, 6 | "chain": "Ethereum", 7 | "endpoint": { 8 | "ethereum": "https://api.thegraph.com/subgraphs/name/blocklytics/bancor" 9 | } 10 | }, 11 | "entities": { 12 | "swap": { 13 | "attributes": { 14 | "user": [ 15 | "trader", 16 | "id" 17 | ], 18 | "tx_id": [ 19 | "transaction", 20 | "id" 21 | ], 22 | "from_token": [ 23 | "fromToken", 24 | "symbol" 25 | ], 26 | "to_token": [ 27 | "toToken", 28 | "symbol" 29 | ], 30 | "from_token_amount": [ 31 | "amountPurchased" 32 | ], 33 | "to_token_amount": [ 34 | "amountReturned" 35 | ], 36 | "timestamp": [ 37 | "timestamp" 38 | ] 39 | }, 40 | "query": { 41 | "name": "swaps", 42 | "extra_fields": {}, 43 | "params": { 44 | "orderBy": "timestamp" 45 | } 46 | }, 47 | "transformations": [] 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /deficrawler/config/block-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "BLocks", 4 | "endpoint": { 5 | "ethereum": "https://api.thegraph.com/subgraphs/name/elkfinance/eth-blocks", 6 | "bsc":"https://api.thegraph.com/subgraphs/name/matthewlilley/bsc-blocks", 7 | "polygon":"https://api.thegraph.com/subgraphs/name/ord786/matic-blocks", 8 | "avalanche": "https://api.thegraph.com/subgraphs/name/radioshackcreator/blocks-avalanche", 9 | "arbitrum": "https://api.thegraph.com/subgraphs/name/elkfinance/arbitrum-blocks", 10 | "optimism": "https://api.thegraph.com/subgraphs/name/beethovenxfi/optimism-blocks", 11 | "fantom": "https://api.thegraph.com/subgraphs/name/beethovenxfi/fantom-blocks" 12 | } 13 | }, 14 | "entities": { 15 | "block": { 16 | "attributes": { 17 | "number": [ 18 | "number" 19 | ], 20 | "timestamp": [ 21 | "timestamp" 22 | ] 23 | }, 24 | "query": { 25 | "name": "blocks", 26 | "extra_fields": {}, 27 | "params": { 28 | "orderBy": "timestamp" 29 | } 30 | }, 31 | "transformations": [] 32 | }, 33 | "block_info": { 34 | "attributes": { 35 | "id": [ 36 | "id" 37 | ], 38 | "number": [ 39 | "number" 40 | ], 41 | "timestamp": [ 42 | "timestamp" 43 | ] 44 | }, 45 | "query": { 46 | "name": "blocks", 47 | "extra_fields": {}, 48 | "params": { 49 | "number": "number" 50 | } 51 | }, 52 | "transformations": [] 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /deficrawler/config/chainlink-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Chainlink", 4 | "type": "Oracle", 5 | "version": 1, 6 | "chain": "Ethereum", 7 | "endpoint": { 8 | "ethereum": "https://api.thegraph.com/subgraphs/name/openpredict/chainlink-prices-subgraph" 9 | } 10 | }, 11 | "entities": { 12 | "pair": { 13 | "attributes": { 14 | "id": [ 15 | "id" 16 | ] 17 | }, 18 | "query": { 19 | "extra_fields": {}, 20 | "name": "assetPairs", 21 | "params": { 22 | "orderBy": "id" 23 | } 24 | }, 25 | "transformations": {} 26 | }, 27 | "price": { 28 | "attributes": { 29 | "pair": [ 30 | "assetPair", 31 | "id" 32 | ], 33 | "price": [ 34 | "price" 35 | ], 36 | "timestamp": [ 37 | "timestamp" 38 | ] 39 | }, 40 | "query": { 41 | "extra_fields": {}, 42 | "name": "prices", 43 | "params": { 44 | "pair": "assetPair", 45 | "orderBy": "timestamp" 46 | } 47 | }, 48 | "transformations": { 49 | "price":"chainlink_prices" 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /deficrawler/config/compound-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Compound", 4 | "type": "Lending", 5 | "version": 2, 6 | "chain": "Ethereum", 7 | "endpoint": { 8 | "ethereum": "https://api.thegraph.com/subgraphs/name/graphprotocol/compound-v2" 9 | } 10 | }, 11 | "entities": { 12 | "borrow": { 13 | "attributes": { 14 | "tx_id": [ 15 | "id" 16 | ], 17 | "user": [ 18 | "borrower" 19 | ], 20 | "token": [ 21 | "underlyingSymbol" 22 | ], 23 | "amount": [ 24 | "amount" 25 | ], 26 | "timestamp": [ 27 | "blockTime" 28 | ] 29 | }, 30 | "query": { 31 | "extra_fields": {}, 32 | "name": "borrowEvents", 33 | "params": { 34 | "orderBy": "blockTime", 35 | "user":"borrower" 36 | } 37 | }, 38 | "transformations": { 39 | "tx_id": "tx_id_hyphen" 40 | } 41 | }, 42 | "deposit": { 43 | "attributes": { 44 | "tx_id": [ 45 | "id" 46 | ], 47 | "user": [ 48 | "to" 49 | ], 50 | "token": [ 51 | "cTokenSymbol" 52 | ], 53 | "amount": [ 54 | "underlyingAmount" 55 | ], 56 | "timestamp": [ 57 | "blockTime" 58 | ] 59 | }, 60 | "query": { 61 | "name": "mintEvents", 62 | "extra_fields": {}, 63 | "params": { 64 | "orderBy": "blockTime", 65 | "user":"to" 66 | } 67 | }, 68 | "transformations": { 69 | "token": "remove_token_prefix", 70 | "tx_id": "tx_id_hyphen" 71 | } 72 | }, 73 | "liquidation": { 74 | "attributes": { 75 | "tx_id": [ 76 | "id" 77 | ], 78 | "user": [ 79 | "from" 80 | ], 81 | "token_principal": [ 82 | "underlyingSymbol" 83 | ], 84 | "token_collateral": [ 85 | "cTokenSymbol" 86 | ], 87 | "amount_principal": [ 88 | "underlyingRepayAmount" 89 | ], 90 | "amount_collateral": [ 91 | "amount" 92 | ], 93 | "liquidator": [ 94 | "to" 95 | ], 96 | "timestamp": [ 97 | "blockTime" 98 | ] 99 | }, 100 | "query": { 101 | "extra_fields": {}, 102 | "name": "liquidationEvents", 103 | "params": { 104 | "orderBy": "blockTime", 105 | "user":"from" 106 | } 107 | }, 108 | "transformations": { 109 | "tx_id": "tx_id_hyphen" 110 | } 111 | }, 112 | "repay": { 113 | "attributes": { 114 | "tx_id": [ 115 | "id" 116 | ], 117 | "user": [ 118 | "payer" 119 | ], 120 | "token": [ 121 | "underlyingSymbol" 122 | ], 123 | "amount": [ 124 | "amount" 125 | ], 126 | "timestamp": [ 127 | "blockTime" 128 | ] 129 | }, 130 | "query": { 131 | "name": "repayEvents", 132 | "extra_fields": {}, 133 | "params": { 134 | "orderBy": "blockTime", 135 | "user":"payer" 136 | } 137 | }, 138 | "transformations": { 139 | "tx_id": "tx_id_hyphen" 140 | } 141 | }, 142 | "redeem": { 143 | "attributes": { 144 | "tx_id": [ 145 | "id" 146 | ], 147 | "user": [ 148 | "to" 149 | ], 150 | "token": [ 151 | "cTokenSymbol" 152 | ], 153 | "amount": [ 154 | "underlyingAmount" 155 | ], 156 | "timestamp": [ 157 | "blockTime" 158 | ] 159 | }, 160 | "query": { 161 | "name": "redeemEvents", 162 | "extra_fields": {}, 163 | "params": { 164 | "orderBy": "blockTime", 165 | "user":"to" 166 | } 167 | }, 168 | "transformations": { 169 | "tx_id": "tx_id_hyphen" 170 | } 171 | }, 172 | "token": { 173 | "attributes": { 174 | "id": [ 175 | "id" 176 | ], 177 | "symbol": [ 178 | "underlyingSymbol" 179 | ] 180 | }, 181 | "query": { 182 | "name": "markets", 183 | "extra_fields": {}, 184 | "params": { 185 | "orderBy": "id", 186 | "initial_value": "0" 187 | } 188 | }, 189 | "transformations": {} 190 | }, 191 | "user": { 192 | "attributes": { 193 | "user_id": [ 194 | "id" 195 | ], 196 | "active_loans": [ 197 | "tokens", 198 | "totalUnderlyingBorrowed" 199 | ], 200 | "liquidations_count": [ 201 | "countLiquidated" 202 | ] 203 | }, 204 | "query": { 205 | "name": "accounts", 206 | "extra_fields": {}, 207 | "params": { 208 | "orderBy": "id", 209 | "initial_value": "0" 210 | } 211 | }, 212 | "transformations": { 213 | "active_loans": "array_length" 214 | } 215 | }, 216 | "user_position": { 217 | "attributes": { 218 | "user_id": [ 219 | "account", 220 | "id" 221 | ], 222 | "symbol": [ 223 | "symbol" 224 | ], 225 | "debt_amount": [ 226 | "totalUnderlyingBorrowed" 227 | ], 228 | "collateral_amount": [ 229 | "totalUnderlyingSupplied" 230 | ] 231 | }, 232 | "query": { 233 | "name": "accountCTokens", 234 | "extra_fields": {}, 235 | "params": { 236 | "user": "account" 237 | } 238 | }, 239 | "transformations": {} 240 | }, 241 | "rates": { 242 | "attributes": { 243 | "token": [ 244 | "underlyingSymbol" 245 | ], 246 | "variable_borrow_rate": [ 247 | "borrowRate" 248 | ], 249 | "stable_borrow_rate": [ 250 | "borrowRate" 251 | ], 252 | "supply_rate": [ 253 | "supplyRate" 254 | ], 255 | "timestamp": [ 256 | "blockTimestamp" 257 | ] 258 | }, 259 | "query": { 260 | "name": "markets", 261 | "extra_fields": {}, 262 | "params": { 263 | "orderBy": "blockTimestamp", 264 | "asset": "id", 265 | "block": true 266 | } 267 | }, 268 | "transformations": { 269 | "variable_borrow_rate": "rates_units_comp", 270 | "stable_borrow_rate": "rates_na", 271 | "supply_rate": "rates_units_comp" 272 | } 273 | }, 274 | "prices": { 275 | "attributes": { 276 | "id": [ 277 | "id" 278 | ], 279 | "symbol": [ 280 | "symbol" 281 | ], 282 | "underlyingAsset": [ 283 | "underlyingSymbol" 284 | ], 285 | "priceInETH": [ 286 | "underlyingPrice" 287 | ], 288 | "priceInUsd": [ 289 | "underlyingPriceUSD" 290 | ], 291 | "exchangeRate": [ 292 | "exchangeRate" 293 | ], 294 | "timestamp": [ 295 | "blockTimestamp" 296 | ] 297 | }, 298 | "query": { 299 | "name": "markets", 300 | "extra_fields": { 301 | }, 302 | "params": { 303 | "orderBy": "blockTimestamp", 304 | "block": "block" 305 | } 306 | }, 307 | "transformations": { 308 | } 309 | } 310 | } 311 | } -------------------------------------------------------------------------------- /deficrawler/config/cream-2-arbitrum.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Cream", 4 | "type": "Lending", 5 | "version": 2, 6 | "chain": "Arbitrum", 7 | "endpoint": { 8 | "arbitrum":"https://api.thegraph.com/subgraphs/name/creamfinancedev/cream-arbitrum" 9 | } 10 | }, 11 | "entities": { 12 | "borrow": { 13 | "attributes": { 14 | "tx_id": [ 15 | "id" 16 | ], 17 | "user": [ 18 | "borrower" 19 | ], 20 | "token": [ 21 | "underlyingSymbol" 22 | ], 23 | "amount": [ 24 | "amount" 25 | ], 26 | "timestamp": [ 27 | "blockTime" 28 | ] 29 | }, 30 | "query": { 31 | "extra_fields": {}, 32 | "name": "borrowEvents", 33 | "params": { 34 | "orderBy": "blockTime", 35 | "user":"borrower" 36 | } 37 | }, 38 | "transformations": { 39 | "tx_id": "tx_id_hyphen" 40 | } 41 | }, 42 | "deposit": { 43 | "attributes": { 44 | "tx_id": [ 45 | "id" 46 | ], 47 | "user": [ 48 | "minter" 49 | ], 50 | "token": [ 51 | "cTokenSymbol" 52 | ], 53 | "amount": [ 54 | "underlyingAmount" 55 | ], 56 | "timestamp": [ 57 | "blockTime" 58 | ] 59 | }, 60 | "query": { 61 | "name": "mintEvents", 62 | "extra_fields": {}, 63 | "params": { 64 | "orderBy": "blockTime", 65 | "user":"to" 66 | } 67 | }, 68 | "transformations": { 69 | "tx_id": "tx_id_hyphen" 70 | } 71 | }, 72 | "liquidation": { 73 | "attributes": { 74 | "tx_id": [ 75 | "id" 76 | ], 77 | "user": [ 78 | "borrower" 79 | ], 80 | "token_principal": [ 81 | "seizeCToken" 82 | ], 83 | "token_collateral": [ 84 | "cToken" 85 | ], 86 | "amount_principal": [ 87 | "underlyingRepayAmount" 88 | ], 89 | "amount_collateral": [ 90 | "underlyingSeizeAmount" 91 | ], 92 | "liquidator": [ 93 | "liquidator" 94 | ], 95 | "timestamp": [ 96 | "blockTime" 97 | ] 98 | }, 99 | "query": { 100 | "extra_fields": {}, 101 | "name": "liquidationEvents", 102 | "params": { 103 | "orderBy": "blockTime", 104 | "user":"from" 105 | } 106 | }, 107 | "transformations": { 108 | "tx_id": "tx_id_hyphen" 109 | } 110 | }, 111 | "repay": { 112 | "attributes": { 113 | "tx_id": [ 114 | "id" 115 | ], 116 | "user": [ 117 | "borrower" 118 | ], 119 | "token": [ 120 | "underlyingSymbol" 121 | ], 122 | "amount": [ 123 | "amount" 124 | ], 125 | "timestamp": [ 126 | "blockTime" 127 | ] 128 | }, 129 | "query": { 130 | "name": "repayEvents", 131 | "extra_fields": {}, 132 | "params": { 133 | "orderBy": "blockTime", 134 | "user":"payer" 135 | } 136 | }, 137 | "transformations": { 138 | "tx_id": "tx_id_hyphen" 139 | } 140 | }, 141 | "user": { 142 | "attributes": { 143 | "user_id": [ 144 | "id" 145 | ], 146 | "active_loans": [ 147 | "tokens", 148 | "totalUnderlyingBorrowed" 149 | ], 150 | "liquidations_count": [ 151 | "countLiquidated" 152 | ] 153 | }, 154 | "query": { 155 | "name": "accounts", 156 | "extra_fields": {}, 157 | "params": { 158 | "orderBy": "id", 159 | "initial_value": "0" 160 | } 161 | }, 162 | "transformations": { 163 | "active_loans": "array_length" 164 | } 165 | }, 166 | "user_position": { 167 | "attributes": { 168 | "user_id": [ 169 | "account", 170 | "id" 171 | ], 172 | "symbol": [ 173 | "symbol" 174 | ], 175 | "debt_amount": [ 176 | "totalUnderlyingBorrowed" 177 | ], 178 | "collateral_amount": [ 179 | "totalUnderlyingSupplied" 180 | ] 181 | }, 182 | "query": { 183 | "name": "accountCTokens", 184 | "extra_fields": {}, 185 | "params": { 186 | "user": "account" 187 | } 188 | }, 189 | "transformations": {} 190 | }, 191 | "redeem": { 192 | "attributes": { 193 | "tx_id": [ 194 | "id" 195 | ], 196 | "user": [ 197 | "redeemer" 198 | ], 199 | "token": [ 200 | "cTokenSymbol" 201 | ], 202 | "amount": [ 203 | "underlyingAmount" 204 | ], 205 | "timestamp": [ 206 | "blockTime" 207 | ] 208 | }, 209 | "query": { 210 | "name": "redeemEvents", 211 | "extra_fields": {}, 212 | "params": { 213 | "orderBy": "blockTime", 214 | "user":"to" 215 | } 216 | }, 217 | "transformations": { 218 | "tx_id": "tx_id_hyphen" 219 | } 220 | }, 221 | "rates": { 222 | "attributes": { 223 | "token": [ 224 | "underlyingSymbol" 225 | ], 226 | "variable_borrow_rate": [ 227 | "borrowRate" 228 | ], 229 | "stable_borrow_rate": [ 230 | "borrowRate" 231 | ], 232 | "supply_rate": [ 233 | "supplyRate" 234 | ], 235 | "timestamp": [ 236 | "blockTimestamp" 237 | ] 238 | }, 239 | "query": { 240 | "name": "markets", 241 | "extra_fields": {}, 242 | "params": { 243 | "orderBy": "blockTimestamp", 244 | "asset": "id", 245 | "block": true 246 | } 247 | }, 248 | "transformations": { 249 | "variable_borrow_rate": "rates_units_comp", 250 | "stable_borrow_rate": "rates_na", 251 | "supply_rate": "rates_units_comp" 252 | } 253 | }, 254 | "token": { 255 | "attributes": { 256 | "id": [ 257 | "id" 258 | ], 259 | "symbol": [ 260 | "underlyingSymbol" 261 | ] 262 | }, 263 | "query": { 264 | "name": "markets", 265 | "extra_fields": {}, 266 | "params": { 267 | "orderBy": "id", 268 | "initial_value": "0" 269 | } 270 | }, 271 | "transformations": {} 272 | }, 273 | "prices": { 274 | "attributes": { 275 | "id": [ 276 | "id" 277 | ], 278 | "symbol": [ 279 | "symbol" 280 | ], 281 | "underlyingAsset": [ 282 | "underlyingSymbol" 283 | ], 284 | "priceInETH": [ 285 | "underlyingPrice" 286 | ], 287 | "priceInUsd": [ 288 | "underlyingPriceUSD" 289 | ], 290 | "exchangeRate": [ 291 | "exchangeRate" 292 | ], 293 | "timestamp": [ 294 | "blockTimestamp" 295 | ] 296 | }, 297 | "query": { 298 | "name": "markets", 299 | "extra_fields": { 300 | }, 301 | "params": { 302 | "orderBy": "blockTimestamp", 303 | "block": "block" 304 | } 305 | }, 306 | "transformations": { 307 | } 308 | } 309 | } 310 | } -------------------------------------------------------------------------------- /deficrawler/config/cream-2-avalanche.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Cream", 4 | "type": "Lending", 5 | "version": 2, 6 | "endpoint": { 7 | "avalanche": "https://api.thegraph.com/subgraphs/name/creamfinancedev/cream-avalanche" 8 | } 9 | }, 10 | "entities": { 11 | "borrow": { 12 | "attributes": { 13 | "tx_id": [ 14 | "id" 15 | ], 16 | "user": [ 17 | "borrower" 18 | ], 19 | "token": [ 20 | "underlyingSymbol" 21 | ], 22 | "amount": [ 23 | "amount" 24 | ], 25 | "timestamp": [ 26 | "blockTime" 27 | ] 28 | }, 29 | "query": { 30 | "extra_fields": {}, 31 | "name": "borrowEvents", 32 | "params": { 33 | "orderBy": "blockTime", 34 | "user":"borrower" 35 | } 36 | }, 37 | "transformations": { 38 | "tx_id": "tx_id_hyphen" 39 | } 40 | }, 41 | "deposit": { 42 | "attributes": { 43 | "tx_id": [ 44 | "id" 45 | ], 46 | "user": [ 47 | "minter" 48 | ], 49 | "token": [ 50 | "cTokenSymbol" 51 | ], 52 | "amount": [ 53 | "underlyingAmount" 54 | ], 55 | "timestamp": [ 56 | "blockTime" 57 | ] 58 | }, 59 | "query": { 60 | "name": "mintEvents", 61 | "extra_fields": {}, 62 | "params": { 63 | "orderBy": "blockTime", 64 | "user":"to" 65 | } 66 | }, 67 | "transformations": { 68 | "tx_id": "tx_id_hyphen" 69 | } 70 | }, 71 | "liquidation": { 72 | "attributes": { 73 | "tx_id": [ 74 | "id" 75 | ], 76 | "user": [ 77 | "borrower" 78 | ], 79 | "token_principal": [ 80 | "seizeCToken" 81 | ], 82 | "token_collateral": [ 83 | "cToken" 84 | ], 85 | "amount_principal": [ 86 | "underlyingRepayAmount" 87 | ], 88 | "amount_collateral": [ 89 | "underlyingSeizeAmount" 90 | ], 91 | "liquidator": [ 92 | "liquidator" 93 | ], 94 | "timestamp": [ 95 | "blockTime" 96 | ] 97 | }, 98 | "query": { 99 | "extra_fields": {}, 100 | "name": "liquidationEvents", 101 | "params": { 102 | "orderBy": "blockTime", 103 | "user":"from" 104 | } 105 | }, 106 | "transformations": { 107 | "tx_id": "tx_id_hyphen" 108 | } 109 | }, 110 | "repay": { 111 | "attributes": { 112 | "tx_id": [ 113 | "id" 114 | ], 115 | "user": [ 116 | "borrower" 117 | ], 118 | "token": [ 119 | "underlyingSymbol" 120 | ], 121 | "amount": [ 122 | "amount" 123 | ], 124 | "timestamp": [ 125 | "blockTime" 126 | ] 127 | }, 128 | "query": { 129 | "name": "repayEvents", 130 | "extra_fields": {}, 131 | "params": { 132 | "orderBy": "blockTime", 133 | "user":"payer" 134 | } 135 | }, 136 | "transformations": { 137 | "tx_id": "tx_id_hyphen" 138 | } 139 | }, 140 | "user": { 141 | "attributes": { 142 | "user_id": [ 143 | "id" 144 | ], 145 | "active_loans": [ 146 | "tokens", 147 | "totalUnderlyingBorrowed" 148 | ], 149 | "liquidations_count": [ 150 | "countLiquidated" 151 | ] 152 | }, 153 | "query": { 154 | "name": "accounts", 155 | "extra_fields": {}, 156 | "params": { 157 | "orderBy": "id", 158 | "initial_value": "0" 159 | } 160 | }, 161 | "transformations": { 162 | "active_loans": "array_length" 163 | } 164 | }, 165 | "user_position": { 166 | "attributes": { 167 | "user_id": [ 168 | "account", 169 | "id" 170 | ], 171 | "symbol": [ 172 | "symbol" 173 | ], 174 | "debt_amount": [ 175 | "totalUnderlyingBorrowed" 176 | ], 177 | "collateral_amount": [ 178 | "totalUnderlyingSupplied" 179 | ] 180 | }, 181 | "query": { 182 | "name": "accountCTokens", 183 | "extra_fields": {}, 184 | "params": { 185 | "user": "account" 186 | } 187 | }, 188 | "transformations": {} 189 | }, 190 | "redeem": { 191 | "attributes": { 192 | "tx_id": [ 193 | "id" 194 | ], 195 | "user": [ 196 | "redeemer" 197 | ], 198 | "token": [ 199 | "cTokenSymbol" 200 | ], 201 | "amount": [ 202 | "underlyingAmount" 203 | ], 204 | "timestamp": [ 205 | "blockTime" 206 | ] 207 | }, 208 | "query": { 209 | "name": "redeemEvents", 210 | "extra_fields": {}, 211 | "params": { 212 | "orderBy": "blockTime", 213 | "user":"to" 214 | } 215 | }, 216 | "transformations": { 217 | "tx_id": "tx_id_hyphen" 218 | } 219 | }, 220 | "rates": { 221 | "attributes": { 222 | "token": [ 223 | "underlyingSymbol" 224 | ], 225 | "variable_borrow_rate": [ 226 | "borrowRate" 227 | ], 228 | "stable_borrow_rate": [ 229 | "borrowRate" 230 | ], 231 | "supply_rate": [ 232 | "supplyRate" 233 | ], 234 | "timestamp": [ 235 | "blockTimestamp" 236 | ] 237 | }, 238 | "query": { 239 | "name": "markets", 240 | "extra_fields": {}, 241 | "params": { 242 | "orderBy": "blockTimestamp", 243 | "asset": "id", 244 | "block": true 245 | } 246 | }, 247 | "transformations": { 248 | "variable_borrow_rate": "rates_units_comp", 249 | "stable_borrow_rate": "rates_na", 250 | "supply_rate": "rates_units_comp" 251 | } 252 | }, 253 | "token": { 254 | "attributes": { 255 | "id": [ 256 | "id" 257 | ], 258 | "symbol": [ 259 | "underlyingSymbol" 260 | ] 261 | }, 262 | "query": { 263 | "name": "markets", 264 | "extra_fields": {}, 265 | "params": { 266 | "orderBy": "id", 267 | "initial_value": "0" 268 | } 269 | }, 270 | "transformations": {} 271 | }, 272 | "prices": { 273 | "attributes": { 274 | "id": [ 275 | "id" 276 | ], 277 | "symbol": [ 278 | "symbol" 279 | ], 280 | "underlyingAsset": [ 281 | "underlyingSymbol" 282 | ], 283 | "priceInETH": [ 284 | "underlyingPrice" 285 | ], 286 | "priceInUsd": [ 287 | "underlyingPriceUSD" 288 | ], 289 | "exchangeRate": [ 290 | "exchangeRate" 291 | ], 292 | "timestamp": [ 293 | "blockTimestamp" 294 | ] 295 | }, 296 | "query": { 297 | "name": "markets", 298 | "extra_fields": { 299 | }, 300 | "params": { 301 | "orderBy": "blockTimestamp", 302 | "block": "block" 303 | } 304 | }, 305 | "transformations": { 306 | } 307 | } 308 | } 309 | } -------------------------------------------------------------------------------- /deficrawler/config/cream-2-fantom.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Cream", 4 | "type": "Lending", 5 | "version": 2, 6 | "endpoint": { 7 | "fantom": "https://api.thegraph.com/subgraphs/name/creamfinancedev/cream-avalanche" 8 | } 9 | }, 10 | "entities": { 11 | "borrow": { 12 | "attributes": { 13 | "tx_id": [ 14 | "id" 15 | ], 16 | "user": [ 17 | "borrower" 18 | ], 19 | "token": [ 20 | "underlyingSymbol" 21 | ], 22 | "amount": [ 23 | "amount" 24 | ], 25 | "timestamp": [ 26 | "blockTime" 27 | ] 28 | }, 29 | "query": { 30 | "extra_fields": {}, 31 | "name": "borrowEvents", 32 | "params": { 33 | "orderBy": "blockTime", 34 | "user":"borrower" 35 | } 36 | }, 37 | "transformations": { 38 | "tx_id": "tx_id_hyphen" 39 | } 40 | }, 41 | "deposit": { 42 | "attributes": { 43 | "tx_id": [ 44 | "id" 45 | ], 46 | "user": [ 47 | "minter" 48 | ], 49 | "token": [ 50 | "cTokenSymbol" 51 | ], 52 | "amount": [ 53 | "underlyingAmount" 54 | ], 55 | "timestamp": [ 56 | "blockTime" 57 | ] 58 | }, 59 | "query": { 60 | "name": "mintEvents", 61 | "extra_fields": {}, 62 | "params": { 63 | "orderBy": "blockTime", 64 | "user":"to" 65 | } 66 | }, 67 | "transformations": { 68 | "tx_id": "tx_id_hyphen" 69 | } 70 | }, 71 | "liquidation": { 72 | "attributes": { 73 | "tx_id": [ 74 | "id" 75 | ], 76 | "user": [ 77 | "borrower" 78 | ], 79 | "token_principal": [ 80 | "seizeCToken" 81 | ], 82 | "token_collateral": [ 83 | "cToken" 84 | ], 85 | "amount_principal": [ 86 | "underlyingRepayAmount" 87 | ], 88 | "amount_collateral": [ 89 | "underlyingSeizeAmount" 90 | ], 91 | "liquidator": [ 92 | "liquidator" 93 | ], 94 | "timestamp": [ 95 | "blockTime" 96 | ] 97 | }, 98 | "query": { 99 | "extra_fields": {}, 100 | "name": "liquidationEvents", 101 | "params": { 102 | "orderBy": "blockTime", 103 | "user":"from" 104 | } 105 | }, 106 | "transformations": { 107 | "tx_id": "tx_id_hyphen" 108 | } 109 | }, 110 | "repay": { 111 | "attributes": { 112 | "tx_id": [ 113 | "id" 114 | ], 115 | "user": [ 116 | "borrower" 117 | ], 118 | "token": [ 119 | "underlyingSymbol" 120 | ], 121 | "amount": [ 122 | "amount" 123 | ], 124 | "timestamp": [ 125 | "blockTime" 126 | ] 127 | }, 128 | "query": { 129 | "name": "repayEvents", 130 | "extra_fields": {}, 131 | "params": { 132 | "orderBy": "blockTime", 133 | "user":"payer" 134 | } 135 | }, 136 | "transformations": { 137 | "tx_id": "tx_id_hyphen" 138 | } 139 | }, 140 | "user": { 141 | "attributes": { 142 | "user_id": [ 143 | "id" 144 | ], 145 | "active_loans": [ 146 | "tokens", 147 | "totalUnderlyingBorrowed" 148 | ], 149 | "liquidations_count": [ 150 | "countLiquidated" 151 | ] 152 | }, 153 | "query": { 154 | "name": "accounts", 155 | "extra_fields": {}, 156 | "params": { 157 | "orderBy": "id", 158 | "initial_value": "0" 159 | } 160 | }, 161 | "transformations": { 162 | "active_loans": "array_length" 163 | } 164 | }, 165 | "user_position": { 166 | "attributes": { 167 | "user_id": [ 168 | "account", 169 | "id" 170 | ], 171 | "symbol": [ 172 | "symbol" 173 | ], 174 | "debt_amount": [ 175 | "totalUnderlyingBorrowed" 176 | ], 177 | "collateral_amount": [ 178 | "totalUnderlyingSupplied" 179 | ] 180 | }, 181 | "query": { 182 | "name": "accountCTokens", 183 | "extra_fields": {}, 184 | "params": { 185 | "user": "account" 186 | } 187 | }, 188 | "transformations": {} 189 | }, 190 | "redeem": { 191 | "attributes": { 192 | "tx_id": [ 193 | "id" 194 | ], 195 | "user": [ 196 | "redeemer" 197 | ], 198 | "token": [ 199 | "cTokenSymbol" 200 | ], 201 | "amount": [ 202 | "underlyingAmount" 203 | ], 204 | "timestamp": [ 205 | "blockTime" 206 | ] 207 | }, 208 | "query": { 209 | "name": "redeemEvents", 210 | "extra_fields": {}, 211 | "params": { 212 | "orderBy": "blockTime", 213 | "user":"to" 214 | } 215 | }, 216 | "transformations": { 217 | "tx_id": "tx_id_hyphen" 218 | } 219 | }, 220 | "rates": { 221 | "attributes": { 222 | "token": [ 223 | "underlyingSymbol" 224 | ], 225 | "variable_borrow_rate": [ 226 | "borrowRate" 227 | ], 228 | "stable_borrow_rate": [ 229 | "borrowRate" 230 | ], 231 | "supply_rate": [ 232 | "supplyRate" 233 | ], 234 | "timestamp": [ 235 | "blockTimestamp" 236 | ] 237 | }, 238 | "query": { 239 | "name": "markets", 240 | "extra_fields": {}, 241 | "params": { 242 | "orderBy": "blockTimestamp", 243 | "asset": "id", 244 | "block": true 245 | } 246 | }, 247 | "transformations": { 248 | "variable_borrow_rate": "rates_units_comp", 249 | "stable_borrow_rate": "rates_na", 250 | "supply_rate": "rates_units_comp" 251 | } 252 | }, 253 | "token": { 254 | "attributes": { 255 | "id": [ 256 | "id" 257 | ], 258 | "symbol": [ 259 | "underlyingSymbol" 260 | ] 261 | }, 262 | "query": { 263 | "name": "markets", 264 | "extra_fields": {}, 265 | "params": { 266 | "orderBy": "id", 267 | "initial_value": "0" 268 | } 269 | }, 270 | "transformations": {} 271 | }, 272 | "prices": { 273 | "attributes": { 274 | "id": [ 275 | "id" 276 | ], 277 | "symbol": [ 278 | "symbol" 279 | ], 280 | "underlyingAsset": [ 281 | "underlyingSymbol" 282 | ], 283 | "priceInETH": [ 284 | "underlyingPrice" 285 | ], 286 | "priceInUsd": [ 287 | "underlyingPriceUSD" 288 | ], 289 | "exchangeRate": [ 290 | "exchangeRate" 291 | ], 292 | "timestamp": [ 293 | "blockTimestamp" 294 | ] 295 | }, 296 | "query": { 297 | "name": "markets", 298 | "extra_fields": { 299 | }, 300 | "params": { 301 | "orderBy": "blockTimestamp", 302 | "block": "block" 303 | } 304 | }, 305 | "transformations": { 306 | } 307 | } 308 | } 309 | } -------------------------------------------------------------------------------- /deficrawler/config/cream-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Cream", 4 | "type": "Lending", 5 | "version": 2, 6 | "chain": "Ethereum", 7 | "endpoint": { 8 | "ethereum": "https://api.thegraph.com/subgraphs/name/creamfinancedev/cream-lending", 9 | "bsc": "https://api.thegraph.com/subgraphs/name/akshaysrivastav/cream-finance-bsc", 10 | "polygon":"https://api.thegraph.com/subgraphs/name/creamfinancedev/cream-polygon", 11 | "arbitrum": "https://api.thegraph.com/subgraphs/name/creamfinancedev/cream-arbitrum" 12 | } 13 | }, 14 | "entities": { 15 | "borrow": { 16 | "attributes": { 17 | "tx_id": [ 18 | "id" 19 | ], 20 | "user": [ 21 | "borrower" 22 | ], 23 | "token": [ 24 | "underlyingSymbol" 25 | ], 26 | "amount": [ 27 | "amount" 28 | ], 29 | "timestamp": [ 30 | "blockTime" 31 | ] 32 | }, 33 | "query": { 34 | "extra_fields": {}, 35 | "name": "borrowEvents", 36 | "params": { 37 | "orderBy": "blockTime", 38 | "user":"borrower" 39 | } 40 | }, 41 | "transformations": { 42 | "tx_id": "tx_id_hyphen" 43 | } 44 | }, 45 | "deposit": { 46 | "attributes": { 47 | "tx_id": [ 48 | "id" 49 | ], 50 | "user": [ 51 | "to" 52 | ], 53 | "token": [ 54 | "cTokenSymbol" 55 | ], 56 | "amount": [ 57 | "underlyingAmount" 58 | ], 59 | "timestamp": [ 60 | "blockTime" 61 | ] 62 | }, 63 | "query": { 64 | "name": "mintEvents", 65 | "extra_fields": {}, 66 | "params": { 67 | "orderBy": "blockTime", 68 | "user":"to" 69 | } 70 | }, 71 | "transformations": { 72 | "tx_id": "tx_id_hyphen" 73 | } 74 | }, 75 | "liquidation": { 76 | "attributes": { 77 | "tx_id": [ 78 | "id" 79 | ], 80 | "user": [ 81 | "from" 82 | ], 83 | "token_principal": [ 84 | "underlyingSymbol" 85 | ], 86 | "token_collateral": [ 87 | "cTokenSymbol" 88 | ], 89 | "amount_principal": [ 90 | "underlyingRepayAmount" 91 | ], 92 | "amount_collateral": [ 93 | "amount" 94 | ], 95 | "liquidator": [ 96 | "to" 97 | ], 98 | "timestamp": [ 99 | "blockTime" 100 | ] 101 | }, 102 | "query": { 103 | "extra_fields": {}, 104 | "name": "liquidationEvents", 105 | "params": { 106 | "orderBy": "blockTime", 107 | "user":"from" 108 | } 109 | }, 110 | "transformations": { 111 | "tx_id": "tx_id_hyphen" 112 | } 113 | }, 114 | "repay": { 115 | "attributes": { 116 | "tx_id": [ 117 | "id" 118 | ], 119 | "user": [ 120 | "payer" 121 | ], 122 | "token": [ 123 | "underlyingSymbol" 124 | ], 125 | "amount": [ 126 | "amount" 127 | ], 128 | "timestamp": [ 129 | "blockTime" 130 | ] 131 | }, 132 | "query": { 133 | "name": "repayEvents", 134 | "extra_fields": {}, 135 | "params": { 136 | "orderBy": "blockTime", 137 | "user":"payer" 138 | } 139 | }, 140 | "transformations": { 141 | "tx_id": "tx_id_hyphen" 142 | } 143 | }, 144 | "user": { 145 | "attributes": { 146 | "user_id": [ 147 | "id" 148 | ], 149 | "active_loans": [ 150 | "tokens", 151 | "totalUnderlyingBorrowed" 152 | ], 153 | "liquidations_count": [ 154 | "countLiquidated" 155 | ] 156 | }, 157 | "query": { 158 | "name": "accounts", 159 | "extra_fields": {}, 160 | "params": { 161 | "orderBy": "id", 162 | "initial_value": "0" 163 | } 164 | }, 165 | "transformations": { 166 | "active_loans": "array_length" 167 | } 168 | }, 169 | "user_position": { 170 | "attributes": { 171 | "user_id": [ 172 | "account", 173 | "id" 174 | ], 175 | "symbol": [ 176 | "symbol" 177 | ], 178 | "debt_amount": [ 179 | "totalUnderlyingBorrowed" 180 | ], 181 | "collateral_amount": [ 182 | "totalUnderlyingSupplied" 183 | ] 184 | }, 185 | "query": { 186 | "name": "accountCTokens", 187 | "extra_fields": {}, 188 | "params": { 189 | "user": "account" 190 | } 191 | }, 192 | "transformations": {} 193 | }, 194 | "redeem": { 195 | "attributes": { 196 | "tx_id": [ 197 | "id" 198 | ], 199 | "user": [ 200 | "to" 201 | ], 202 | "token": [ 203 | "cTokenSymbol" 204 | ], 205 | "amount": [ 206 | "underlyingAmount" 207 | ], 208 | "timestamp": [ 209 | "blockTime" 210 | ] 211 | }, 212 | "query": { 213 | "name": "redeemEvents", 214 | "extra_fields": {}, 215 | "params": { 216 | "orderBy": "blockTime", 217 | "user":"to" 218 | } 219 | }, 220 | "transformations": { 221 | "tx_id": "tx_id_hyphen" 222 | } 223 | }, 224 | "rates": { 225 | "attributes": { 226 | "token": [ 227 | "underlyingSymbol" 228 | ], 229 | "variable_borrow_rate": [ 230 | "borrowRate" 231 | ], 232 | "stable_borrow_rate": [ 233 | "borrowRate" 234 | ], 235 | "supply_rate": [ 236 | "supplyRate" 237 | ], 238 | "timestamp": [ 239 | "blockTimestamp" 240 | ] 241 | }, 242 | "query": { 243 | "name": "markets", 244 | "extra_fields": {}, 245 | "params": { 246 | "orderBy": "blockTimestamp", 247 | "asset": "id", 248 | "block": true 249 | } 250 | }, 251 | "transformations": { 252 | "variable_borrow_rate": "rates_units_comp", 253 | "stable_borrow_rate": "rates_na", 254 | "supply_rate": "rates_units_comp" 255 | } 256 | }, 257 | "token": { 258 | "attributes": { 259 | "id": [ 260 | "id" 261 | ], 262 | "symbol": [ 263 | "underlyingSymbol" 264 | ] 265 | }, 266 | "query": { 267 | "name": "markets", 268 | "extra_fields": {}, 269 | "params": { 270 | "orderBy": "id", 271 | "initial_value": "0" 272 | } 273 | }, 274 | "transformations": {} 275 | }, 276 | "prices": { 277 | "attributes": { 278 | "id": [ 279 | "id" 280 | ], 281 | "symbol": [ 282 | "symbol" 283 | ], 284 | "underlyingAsset": [ 285 | "underlyingSymbol" 286 | ], 287 | "priceInETH": [ 288 | "underlyingPrice" 289 | ], 290 | "priceInUsd": [ 291 | "underlyingPriceUSD" 292 | ], 293 | "exchangeRate": [ 294 | "exchangeRate" 295 | ], 296 | "timestamp": [ 297 | "blockTimestamp" 298 | ] 299 | }, 300 | "query": { 301 | "name": "markets", 302 | "extra_fields": { 303 | }, 304 | "params": { 305 | "orderBy": "blockTimestamp", 306 | "block": "block" 307 | } 308 | }, 309 | "transformations": { 310 | } 311 | } 312 | } 313 | } -------------------------------------------------------------------------------- /deficrawler/config/dodoex-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Dodoex", 4 | "type": "Descentralized Exchange", 5 | "version": 2, 6 | "endpoint": { 7 | "ethereum": "https://api.thegraph.com/subgraphs/name/dodoex/dodoex-v2", 8 | "bsc": "https://api.thegraph.com/subgraphs/name/dodoex/dodoex-v2-bsc", 9 | "polygon": "https://api.thegraph.com/subgraphs/name/dodoex/dodoex-v2-polygon", 10 | "arbitrum": "https://api.thegraph.com/subgraphs/name/dodoex/dodoex-v2-arbitrum" 11 | } 12 | }, 13 | "entities": { 14 | "swap": { 15 | "attributes": { 16 | "user": [ 17 | "sender" 18 | ], 19 | "tx_id": [ 20 | "hash" 21 | ], 22 | "from_token": [ 23 | "fromToken", 24 | "symbol" 25 | ], 26 | "to_token": [ 27 | "toToken", 28 | "symbol" 29 | ], 30 | "from_token_amount": [ 31 | "amountIn" 32 | ], 33 | "to_token_amount": [ 34 | "amountOut" 35 | ], 36 | "pool": [ 37 | "pair", 38 | "id" 39 | ], 40 | "amount_usd": [ 41 | "volumeUSD" 42 | ], 43 | "timestamp": [ 44 | "timestamp" 45 | ] 46 | }, 47 | "query": { 48 | "name": "swaps", 49 | "extra_fields": {}, 50 | "params": { 51 | "orderBy": "timestamp", 52 | "pool": "pair" 53 | } 54 | }, 55 | "transformations": {} 56 | }, 57 | "pool": { 58 | "attributes": { 59 | "id": [ 60 | "id" 61 | ], 62 | "pool_tokens": [ 63 | [ 64 | "token0", 65 | "symbol" 66 | ], 67 | [ 68 | "token1", 69 | "symbol" 70 | ] 71 | ], 72 | "created_at": [ 73 | "createdAtTimestamp" 74 | ] 75 | }, 76 | "query": { 77 | "name": "pairs", 78 | "extra_fields": {}, 79 | "params": { 80 | "orderBy": "id", 81 | "initial_value": "0" 82 | } 83 | }, 84 | "transformations": { 85 | "pool_tokens": "concat_symbols" 86 | } 87 | }, 88 | "mint": { 89 | "attributes": { 90 | "tx_id": [ 91 | "transaction", 92 | "id" 93 | ], 94 | "token0": [ 95 | "pair", 96 | "token0", 97 | "symbol" 98 | ], 99 | "token1": [ 100 | "pair", 101 | "token1", 102 | "symbol" 103 | ], 104 | "amount0": [ 105 | "amount0" 106 | ], 107 | "amount1": [ 108 | "amount1" 109 | ], 110 | "user": [ 111 | "to" 112 | ], 113 | "pool": [ 114 | "pair", 115 | "id" 116 | ], 117 | "timestamp": [ 118 | "timestamp" 119 | ] 120 | }, 121 | "query": { 122 | "name": "mints", 123 | "extra_fields": {}, 124 | "params": { 125 | "orderBy": "timestamp" 126 | } 127 | }, 128 | "transformations": {} 129 | }, 130 | "burn": { 131 | "attributes": { 132 | "tx_id": [ 133 | "transaction", 134 | "id" 135 | ], 136 | "token0": [ 137 | "pair", 138 | "token0", 139 | "symbol" 140 | ], 141 | "token1": [ 142 | "pair", 143 | "token1", 144 | "symbol" 145 | ], 146 | "amount0": [ 147 | "amount0" 148 | ], 149 | "amount1": [ 150 | "amount1" 151 | ], 152 | "user": [ 153 | "sender" 154 | ], 155 | "pool": [ 156 | "pair", 157 | "id" 158 | ], 159 | "timestamp": [ 160 | "timestamp" 161 | ] 162 | }, 163 | "query": { 164 | "name": "burns", 165 | "extra_fields": {}, 166 | "params": { 167 | "orderBy": "timestamp" 168 | } 169 | }, 170 | "transformations": {} 171 | }, 172 | "pool_volume_hourly": { 173 | "attributes": { 174 | "id": [ 175 | "pairAddress" 176 | ], 177 | "token0": [ 178 | "baseToken", 179 | "id" 180 | ], 181 | "token1": [ 182 | "quoteToken", 183 | "id" 184 | ], 185 | "liquidity": [ 186 | "volumeUSD" 187 | ], 188 | "hourlyVolumeUSD": [ 189 | "volumeUSD" 190 | ], 191 | "hourlyVolumeToken0": [ 192 | "volumeBase" 193 | ], 194 | "hourlyVolumeToken1": [ 195 | "volumeQuote" 196 | ], 197 | "hourlyTxns": [ 198 | "txns" 199 | ], 200 | "hourStartUnix": [ 201 | "hour" 202 | ] 203 | }, 204 | "query": { 205 | "name": "pairHourDatas", 206 | "extra_fields": {}, 207 | "params": { 208 | "orderBy": "hour", 209 | "pool": "pairAddress" 210 | } 211 | }, 212 | "transformations": { 213 | "hourlyVolumeUSD": "na" 214 | } 215 | } 216 | } 217 | } -------------------------------------------------------------------------------- /deficrawler/config/global.json: -------------------------------------------------------------------------------- 1 | { 2 | "supported_entities": { 3 | "lending": [ 4 | "borrow", 5 | "deposit", 6 | "liquidation", 7 | "repay" 8 | ], 9 | "dex": [ 10 | "swap", 11 | "pool" 12 | ] 13 | } 14 | } -------------------------------------------------------------------------------- /deficrawler/config/kashi-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Kashi", 4 | "type": "Lending", 5 | "version": 1, 6 | "endpoint": { 7 | "ethereum": "https://api.thegraph.com/subgraphs/name/sushiswap/bentobox", 8 | "polygon": "https://api.thegraph.com/subgraphs/name/sushiswap/matic-bentobox", 9 | "xdai": "https://api.thegraph.com/subgraphs/name/sushiswap/xdai-bentobox", 10 | "fantom": "https://api.thegraph.com/subgraphs/name/sushiswap/fantom-bentobox" 11 | } 12 | }, 13 | "entities": { 14 | "borrow": { 15 | "attributes": { 16 | "tx_id": [ 17 | "id" 18 | ], 19 | "user": [ 20 | "root", 21 | "user", 22 | "id" 23 | ], 24 | "token": [ 25 | "token", 26 | "symbol" 27 | ], 28 | "amount": [ 29 | "amount" 30 | ], 31 | "timestamp": [ 32 | "timestamp" 33 | ] 34 | }, 35 | "query": { 36 | "extra_fields": { 37 | "decimals": [ 38 | "token", 39 | "decimals" 40 | ] 41 | }, 42 | "name": "kashiPairActions", 43 | "params": { 44 | "orderBy": "timestamp", 45 | "type": "borrow", 46 | "user": "root_contains" 47 | } 48 | }, 49 | "transformations": { 50 | "timestamp": "to_int", 51 | "tx_id": "tx_id_hyphen", 52 | "amount": "decimals" 53 | } 54 | }, 55 | "repay": { 56 | "attributes": { 57 | "tx_id": [ 58 | "id" 59 | ], 60 | "user": [ 61 | "root", 62 | "user", 63 | "id" 64 | ], 65 | "token": [ 66 | "token", 67 | "symbol" 68 | ], 69 | "amount": [ 70 | "amount" 71 | ], 72 | "timestamp": [ 73 | "timestamp" 74 | ] 75 | }, 76 | "query": { 77 | "name": "kashiPairActions", 78 | "extra_fields": { 79 | "decimals": [ 80 | "token", 81 | "decimals" 82 | ] 83 | }, 84 | "params": { 85 | "orderBy": "timestamp", 86 | "type": "repay", 87 | "user": "root_contains" 88 | } 89 | }, 90 | "transformations": { 91 | "timestamp": "to_int", 92 | "tx_id": "tx_id_hyphen", 93 | "amount": "decimals" 94 | } 95 | }, 96 | "deposit": { 97 | "attributes": { 98 | "tx_id": [ 99 | "id" 100 | ], 101 | "user": [ 102 | "root", 103 | "user", 104 | "id" 105 | ], 106 | "token": [ 107 | "token", 108 | "symbol" 109 | ], 110 | "amount": [ 111 | "share" 112 | ], 113 | "timestamp": [ 114 | "timestamp" 115 | ] 116 | }, 117 | "query": { 118 | "extra_fields": { 119 | "decimals": [ 120 | "token", 121 | "decimals" 122 | ] 123 | }, 124 | "name": "kashiPairActions", 125 | "params": { 126 | "orderBy": "timestamp", 127 | "type": "addCollateral", 128 | "user": "root_contains" 129 | } 130 | }, 131 | "transformations": { 132 | "timestamp": "to_int", 133 | "tx_id": "tx_id_hyphen", 134 | "amount": "decimals" 135 | } 136 | }, 137 | "redeem": { 138 | "attributes": { 139 | "tx_id": [ 140 | "id" 141 | ], 142 | "user": [ 143 | "root", 144 | "user", 145 | "id" 146 | ], 147 | "token": [ 148 | "token", 149 | "symbol" 150 | ], 151 | "amount": [ 152 | "share" 153 | ], 154 | "timestamp": [ 155 | "timestamp" 156 | ] 157 | }, 158 | "query": { 159 | "extra_fields": { 160 | "decimals": [ 161 | "token", 162 | "decimals" 163 | ] 164 | }, 165 | "name": "kashiPairActions", 166 | "params": { 167 | "orderBy": "timestamp", 168 | "type": "removeCollateral", 169 | "user": "root_contains" 170 | } 171 | }, 172 | "transformations": { 173 | "timestamp": "to_int", 174 | "tx_id": "tx_id_hyphen", 175 | "amount": "decimals" 176 | } 177 | } 178 | } 179 | } -------------------------------------------------------------------------------- /deficrawler/config/kyber-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Kyber", 4 | "type": "Kyber", 5 | "version": 1, 6 | "chain": "Ethereum", 7 | "endpoint": { 8 | "ethereum": "https://api.thegraph.com/subgraphs/name/protofire/kyber" 9 | } 10 | }, 11 | "entities": { 12 | "swap": { 13 | "attributes": { 14 | "user": [ 15 | "trader", 16 | "id" 17 | ], 18 | "tx_id": [ 19 | "id" 20 | ], 21 | "from_token": [ 22 | "src", 23 | "symbol" 24 | ], 25 | "to_token": [ 26 | "desr", 27 | "symbol" 28 | ], 29 | "from_token_amount": [ 30 | "rawSrcAmount" 31 | ], 32 | "to_token_amount": [ 33 | "rawDestAmount" 34 | ], 35 | "timestamp": [ 36 | "createdAtBlockTimestamp" 37 | ] 38 | }, 39 | "query": { 40 | "name": "fullTrades", 41 | "extra_fields": {}, 42 | "params": { 43 | "orderBy": "createdAtBlockTimestamp" 44 | } 45 | }, 46 | "transformations": {} 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /deficrawler/config/pancakeswap-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Pancakeswap", 4 | "type": "Descentralized Exchange", 5 | "version": 2, 6 | "chain": "bsc", 7 | "endpoint": { 8 | "bsc": "https://api.thegraph.com/subgraphs/name/elrakabawi/pancakeswap" 9 | } 10 | }, 11 | "entities": { 12 | "swap": { 13 | "attributes": { 14 | "user": [ 15 | "sender" 16 | ], 17 | "tx_id": [ 18 | "transaction", 19 | "id" 20 | ], 21 | "from_token": [ 22 | [ 23 | "pair", 24 | "token0", 25 | "symbol" 26 | ], 27 | [ 28 | "pair", 29 | "token1", 30 | "symbol" 31 | ] 32 | ], 33 | "to_token": [ 34 | [ 35 | "pair", 36 | "token0", 37 | "symbol" 38 | ], 39 | [ 40 | "pair", 41 | "token1", 42 | "symbol" 43 | ] 44 | ], 45 | "from_token_amount": [ 46 | [ 47 | "amount0In" 48 | ], 49 | [ 50 | "amount1In" 51 | ] 52 | ], 53 | "to_token_amount": [ 54 | [ 55 | "amount0Out" 56 | ], 57 | [ 58 | "amount1Out" 59 | ] 60 | ], 61 | "pool": [ 62 | "pair", 63 | "id" 64 | ], 65 | "timestamp": [ 66 | "timestamp" 67 | ] 68 | }, 69 | "query": { 70 | "name": "swaps", 71 | "extra_fields": {}, 72 | "params": { 73 | "orderBy": "timestamp", 74 | "pool": "pair" 75 | } 76 | }, 77 | "transformations": { 78 | "from_token": "from_token", 79 | "to_token": "to_token", 80 | "from_token_amount": "from_token_amount", 81 | "to_token_amount": "to_token_amount" 82 | } 83 | }, 84 | "pool": { 85 | "attributes": { 86 | "id": [ 87 | "id" 88 | ], 89 | "pool_tokens": [ 90 | [ 91 | "token0", 92 | "symbol" 93 | ], 94 | [ 95 | "token1", 96 | "symbol" 97 | ] 98 | ], 99 | "created_at": [ 100 | "createdAtTimestamp" 101 | ], 102 | "liquidity_usd": [ 103 | "reserveUSD" 104 | ] 105 | }, 106 | "query": { 107 | "name": "pairs", 108 | "extra_fields": {}, 109 | "params": { 110 | "orderBy": "id", 111 | "initial_value": "0" 112 | } 113 | }, 114 | "transformations": { 115 | "pool_tokens": "concat_symbols" 116 | } 117 | } 118 | } 119 | } -------------------------------------------------------------------------------- /deficrawler/config/pancakeswap-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Pancakeswap", 4 | "type": "Descentralized Exchange", 5 | "version": 2, 6 | "chain": "Bsc", 7 | "endpoint": { 8 | "bsc": "https://api.thegraph.com/subgraphs/name/henry0717/pancakeswapv2" 9 | } 10 | }, 11 | "entities": { 12 | "swap": { 13 | "attributes": { 14 | "user": [ 15 | "sender" 16 | ], 17 | "tx_id": [ 18 | "transaction", 19 | "id" 20 | ], 21 | "from_token": [ 22 | [ 23 | "pair", 24 | "token0", 25 | "symbol" 26 | ], 27 | [ 28 | "pair", 29 | "token1", 30 | "symbol" 31 | ] 32 | ], 33 | "to_token": [ 34 | [ 35 | "pair", 36 | "token0", 37 | "symbol" 38 | ], 39 | [ 40 | "pair", 41 | "token1", 42 | "symbol" 43 | ] 44 | ], 45 | "from_token_amount": [ 46 | [ 47 | "amount0In" 48 | ], 49 | [ 50 | "amount1In" 51 | ] 52 | ], 53 | "to_token_amount": [ 54 | [ 55 | "amount0Out" 56 | ], 57 | [ 58 | "amount1Out" 59 | ] 60 | ], 61 | "pool": [ 62 | "pair", 63 | "id" 64 | ], 65 | "amount_usd": [ 66 | "amountUSD" 67 | ], 68 | "timestamp": [ 69 | "timestamp" 70 | ] 71 | }, 72 | "query": { 73 | "name": "swaps", 74 | "extra_fields": {}, 75 | "params": { 76 | "orderBy": "timestamp", 77 | "pool": "pair" 78 | } 79 | }, 80 | "transformations": { 81 | "from_token": "from_token", 82 | "to_token": "to_token", 83 | "from_token_amount": "from_token_amount", 84 | "to_token_amount": "to_token_amount" 85 | } 86 | }, 87 | "pool": { 88 | "attributes": { 89 | "id": [ 90 | "id" 91 | ], 92 | "pool_tokens": [ 93 | [ 94 | "token0", 95 | "symbol" 96 | ], 97 | [ 98 | "token1", 99 | "symbol" 100 | ] 101 | ], 102 | "created_at": [ 103 | "createdAtTimestamp" 104 | ], 105 | "liquidity_usd": [ 106 | "reserveUSD" 107 | ] 108 | }, 109 | "query": { 110 | "name": "pairs", 111 | "extra_fields": {}, 112 | "params": { 113 | "orderBy": "id", 114 | "initial_value": "0" 115 | } 116 | }, 117 | "transformations": { 118 | "pool_tokens": "concat_symbols" 119 | } 120 | }, 121 | "mint": { 122 | "attributes": { 123 | "tx_id": [ 124 | "transaction", 125 | "id" 126 | ], 127 | "token0": [ 128 | "pair", 129 | "token0", 130 | "symbol" 131 | ], 132 | "token1": [ 133 | "pair", 134 | "token1", 135 | "symbol" 136 | ], 137 | "amount0": [ 138 | "amount0" 139 | ], 140 | "amount1": [ 141 | "amount1" 142 | ], 143 | "user": [ 144 | "to" 145 | ], 146 | "pool": [ 147 | "pair", 148 | "id" 149 | ], 150 | "timestamp": [ 151 | "timestamp" 152 | ] 153 | }, 154 | "query": { 155 | "name": "mints", 156 | "extra_fields": {}, 157 | "params": { 158 | "orderBy": "timestamp" 159 | } 160 | }, 161 | "transformations": {} 162 | }, 163 | "burn": { 164 | "attributes": { 165 | "tx_id": [ 166 | "transaction", 167 | "id" 168 | ], 169 | "token0": [ 170 | "pair", 171 | "token0", 172 | "symbol" 173 | ], 174 | "token1": [ 175 | "pair", 176 | "token1", 177 | "symbol" 178 | ], 179 | "amount0": [ 180 | "amount0" 181 | ], 182 | "amount1": [ 183 | "amount1" 184 | ], 185 | "user": [ 186 | "sender" 187 | ], 188 | "pool": [ 189 | "pair", 190 | "id" 191 | ], 192 | "timestamp": [ 193 | "timestamp" 194 | ] 195 | }, 196 | "query": { 197 | "name": "burns", 198 | "extra_fields": {}, 199 | "params": { 200 | "orderBy": "timestamp" 201 | } 202 | }, 203 | "transformations": {} 204 | }, 205 | "pool_volume_hourly": { 206 | "attributes": { 207 | "id": [ 208 | "pair", 209 | "id" 210 | ], 211 | "token0":[ 212 | "reserve0" 213 | ], 214 | "token1":[ 215 | "reserve1" 216 | ], 217 | "liquidity":[ 218 | "reserveUSD" 219 | ], 220 | "hourlyVolumeUSD":[ 221 | "hourlyVolumeUSD" 222 | ], 223 | "hourlyVolumeToken0":[ 224 | "hourlyVolumeToken0" 225 | ], 226 | "hourlyVolumeToken1":[ 227 | "hourlyVolumeToken1" 228 | ], 229 | "hourlyTxns":[ 230 | "hourlyTxns" 231 | ], 232 | "hourStartUnix": [ 233 | "hourStartUnix" 234 | ] 235 | }, 236 | "query": { 237 | "name": "pairHourDatas", 238 | "extra_fields": {}, 239 | "params": { 240 | "orderBy": "hourStartUnix", 241 | "pool": "pair" 242 | } 243 | }, 244 | "transformations": { 245 | } 246 | } 247 | } 248 | } -------------------------------------------------------------------------------- /deficrawler/config/pangolin-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Pangolin", 4 | "type": "Descentralized Exchange", 5 | "version": 1, 6 | "endpoint": { 7 | "avalanche": "https://api.thegraph.com/subgraphs/name/token-terminal/pangolin-v1-avalanche" 8 | } 9 | }, 10 | "entities": { 11 | "swap": { 12 | "attributes": { 13 | "user": [ 14 | "sender" 15 | ], 16 | "tx_id": [ 17 | "transaction", 18 | "id" 19 | ], 20 | "from_token": [ 21 | [ 22 | "pair", 23 | "token0", 24 | "symbol" 25 | ], 26 | [ 27 | "pair", 28 | "token1", 29 | "symbol" 30 | ] 31 | ], 32 | "to_token": [ 33 | [ 34 | "pair", 35 | "token0", 36 | "symbol" 37 | ], 38 | [ 39 | "pair", 40 | "token1", 41 | "symbol" 42 | ] 43 | ], 44 | "from_token_amount": [ 45 | [ 46 | "amount0In" 47 | ], 48 | [ 49 | "amount1In" 50 | ] 51 | ], 52 | "to_token_amount": [ 53 | [ 54 | "amount0Out" 55 | ], 56 | [ 57 | "amount1Out" 58 | ] 59 | ], 60 | "pool": [ 61 | "pair", 62 | "id" 63 | ], 64 | "amount_usd": [ 65 | "amountUSD" 66 | ], 67 | "timestamp": [ 68 | "timestamp" 69 | ] 70 | }, 71 | "query": { 72 | "name": "swaps", 73 | "extra_fields": {}, 74 | "params": { 75 | "orderBy": "timestamp", 76 | "pool": "pair" 77 | } 78 | }, 79 | "transformations": { 80 | "from_token": "from_token", 81 | "to_token": "to_token", 82 | "from_token_amount": "from_token_amount", 83 | "to_token_amount": "to_token_amount" 84 | } 85 | }, 86 | "pool": { 87 | "attributes": { 88 | "id": [ 89 | "id" 90 | ], 91 | "pool_tokens": [ 92 | [ 93 | "token0", 94 | "symbol" 95 | ], 96 | [ 97 | "token1", 98 | "symbol" 99 | ] 100 | ], 101 | "created_at": [ 102 | "createdAtTimestamp" 103 | ], 104 | "liquidity_usd": [ 105 | "reserveUSD" 106 | ] 107 | }, 108 | "query": { 109 | "name": "pairs", 110 | "extra_fields": {}, 111 | "params": { 112 | "orderBy": "id", 113 | "initial_value": "0" 114 | } 115 | }, 116 | "transformations": { 117 | "pool_tokens": "concat_symbols" 118 | } 119 | }, 120 | "mint": { 121 | "attributes": { 122 | "tx_id": [ 123 | "transaction", 124 | "id" 125 | ], 126 | "token0": [ 127 | "pair", 128 | "token0", 129 | "symbol" 130 | ], 131 | "token1": [ 132 | "pair", 133 | "token1", 134 | "symbol" 135 | ], 136 | "amount0": [ 137 | "amount0" 138 | ], 139 | "amount1": [ 140 | "amount1" 141 | ], 142 | "user": [ 143 | "to" 144 | ], 145 | "pool": [ 146 | "pair", 147 | "id" 148 | ], 149 | "timestamp": [ 150 | "timestamp" 151 | ] 152 | }, 153 | "query": { 154 | "name": "mints", 155 | "extra_fields": {}, 156 | "params": { 157 | "orderBy": "timestamp" 158 | } 159 | }, 160 | "transformations": {} 161 | }, 162 | "burn": { 163 | "attributes": { 164 | "tx_id": [ 165 | "transaction", 166 | "id" 167 | ], 168 | "token0": [ 169 | "pair", 170 | "token0", 171 | "symbol" 172 | ], 173 | "token1": [ 174 | "pair", 175 | "token1", 176 | "symbol" 177 | ], 178 | "amount0": [ 179 | "amount0" 180 | ], 181 | "amount1": [ 182 | "amount1" 183 | ], 184 | "user": [ 185 | "sender" 186 | ], 187 | "pool": [ 188 | "pair", 189 | "id" 190 | ], 191 | "timestamp": [ 192 | "timestamp" 193 | ] 194 | }, 195 | "query": { 196 | "name": "burns", 197 | "extra_fields": {}, 198 | "params": { 199 | "orderBy": "timestamp" 200 | } 201 | }, 202 | "transformations": {} 203 | }, 204 | "pool_volume_hourly": { 205 | "attributes": { 206 | "id": [ 207 | "pair", 208 | "id" 209 | ], 210 | "token0": [ 211 | "reserve0" 212 | ], 213 | "token1": [ 214 | "reserve1" 215 | ], 216 | "liquidity": [ 217 | "reserveUSD" 218 | ], 219 | "hourlyVolumeUSD": [ 220 | "hourlyVolumeUSD" 221 | ], 222 | "hourlyVolumeToken0": [ 223 | "hourlyVolumeToken0" 224 | ], 225 | "hourlyVolumeToken1": [ 226 | "hourlyVolumeToken1" 227 | ], 228 | "hourlyTxns": [ 229 | "hourlyTxns" 230 | ], 231 | "hourStartUnix": [ 232 | "hourStartUnix" 233 | ] 234 | }, 235 | "query": { 236 | "name": "pairHourDatas", 237 | "extra_fields": {}, 238 | "params": { 239 | "orderBy": "hourStartUnix", 240 | "pool": "pair" 241 | } 242 | }, 243 | "transformations": {} 244 | } 245 | } 246 | } -------------------------------------------------------------------------------- /deficrawler/config/protocol_template.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "", 4 | "type": "", 5 | "version": 1, 6 | "chain": "", 7 | "endpoint": { 8 | "ethereum": "" 9 | } 10 | }, 11 | "entities": { 12 | "borrow": { 13 | "attributes": {}, 14 | "query": { 15 | "extra_fields": {}, 16 | "name": "borrows", 17 | "params": { 18 | "orderBy": "timestamp" 19 | } 20 | }, 21 | "transformations": {} 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /deficrawler/config/quickswap-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "QuickSwap", 4 | "type": "Descentralized Exchange", 5 | "version": 1, 6 | "endpoint": { 7 | "polygon": "https://api.thegraph.com/subgraphs/name/proy24/quickswap-polygon" 8 | } 9 | }, 10 | "entities": { 11 | "swap": { 12 | "attributes": { 13 | "user": [ 14 | "sender" 15 | ], 16 | "tx_id": [ 17 | "transaction", 18 | "id" 19 | ], 20 | "from_token": [ 21 | [ 22 | "pair", 23 | "token0", 24 | "symbol" 25 | ], 26 | [ 27 | "pair", 28 | "token1", 29 | "symbol" 30 | ] 31 | ], 32 | "to_token": [ 33 | [ 34 | "pair", 35 | "token0", 36 | "symbol" 37 | ], 38 | [ 39 | "pair", 40 | "token1", 41 | "symbol" 42 | ] 43 | ], 44 | "from_token_amount": [ 45 | [ 46 | "amount0In" 47 | ], 48 | [ 49 | "amount1In" 50 | ] 51 | ], 52 | "to_token_amount": [ 53 | [ 54 | "amount0Out" 55 | ], 56 | [ 57 | "amount1Out" 58 | ] 59 | ], 60 | "pool": [ 61 | "pair", 62 | "id" 63 | ], 64 | "amount_usd": [ 65 | "amountUSD" 66 | ], 67 | "timestamp": [ 68 | "timestamp" 69 | ] 70 | }, 71 | "query": { 72 | "name": "swaps", 73 | "extra_fields": {}, 74 | "params": { 75 | "orderBy": "timestamp", 76 | "pool": "pair" 77 | } 78 | }, 79 | "transformations": { 80 | "from_token": "from_token", 81 | "to_token": "to_token", 82 | "from_token_amount": "from_token_amount", 83 | "to_token_amount": "to_token_amount" 84 | } 85 | }, 86 | "pool": { 87 | "attributes": { 88 | "id": [ 89 | "id" 90 | ], 91 | "pool_tokens": [ 92 | [ 93 | "token0", 94 | "symbol" 95 | ], 96 | [ 97 | "token1", 98 | "symbol" 99 | ] 100 | ], 101 | "created_at":[ 102 | "createdAtTimestamp" 103 | ], 104 | "liquidity_usd": [ 105 | "reserveUSD" 106 | ] 107 | }, 108 | "query": { 109 | "name": "pairs", 110 | "extra_fields": {}, 111 | "params": { 112 | "orderBy": "id", 113 | "initial_value": "0" 114 | } 115 | }, 116 | "transformations": { 117 | "pool_tokens": "concat_symbols" 118 | } 119 | }, 120 | "mint": { 121 | "attributes": { 122 | "tx_id": [ 123 | "transaction", 124 | "id" 125 | ], 126 | "token0": [ 127 | "pair", 128 | "token0", 129 | "symbol" 130 | ], 131 | "token1": [ 132 | "pair", 133 | "token1", 134 | "symbol" 135 | ], 136 | "amount0": [ 137 | "amount0" 138 | ], 139 | "amount1": [ 140 | "amount1" 141 | ], 142 | "user": [ 143 | "to" 144 | ], 145 | "pool": [ 146 | "pair", 147 | "id" 148 | ], 149 | "timestamp": [ 150 | "timestamp" 151 | ] 152 | }, 153 | "query": { 154 | "name": "mints", 155 | "extra_fields": {}, 156 | "params": { 157 | "orderBy": "timestamp" 158 | } 159 | }, 160 | "transformations": {} 161 | }, 162 | "burn": { 163 | "attributes": { 164 | "tx_id": [ 165 | "transaction", 166 | "id" 167 | ], 168 | "token0": [ 169 | "pair", 170 | "token0", 171 | "symbol" 172 | ], 173 | "token1": [ 174 | "pair", 175 | "token1", 176 | "symbol" 177 | ], 178 | "amount0": [ 179 | "amount0" 180 | ], 181 | "amount1": [ 182 | "amount1" 183 | ], 184 | "user": [ 185 | "sender" 186 | ], 187 | "pool": [ 188 | "pair", 189 | "id" 190 | ], 191 | "timestamp": [ 192 | "timestamp" 193 | ] 194 | }, 195 | "query": { 196 | "name": "burns", 197 | "extra_fields": {}, 198 | "params": { 199 | "orderBy": "timestamp" 200 | } 201 | }, 202 | "transformations": {} 203 | }, 204 | "pool_volume_hourly": { 205 | "attributes": { 206 | "id": [ 207 | "pair", 208 | "id" 209 | ], 210 | "token0":[ 211 | "reserve0" 212 | ], 213 | "token1":[ 214 | "reserve1" 215 | ], 216 | "liquidity":[ 217 | "reserveUSD" 218 | ], 219 | "hourlyVolumeUSD":[ 220 | "hourlyVolumeUSD" 221 | ], 222 | "hourlyVolumeToken0":[ 223 | "hourlyVolumeToken0" 224 | ], 225 | "hourlyVolumeToken1":[ 226 | "hourlyVolumeToken1" 227 | ], 228 | "hourlyTxns":[ 229 | "hourlyTxns" 230 | ], 231 | "hourStartUnix": [ 232 | "hourStartUnix" 233 | ] 234 | }, 235 | "query": { 236 | "name": "pairHourDatas", 237 | "extra_fields": {}, 238 | "params": { 239 | "orderBy": "hourStartUnix", 240 | "pool": "pair" 241 | } 242 | }, 243 | "transformations": { 244 | } 245 | } 246 | } 247 | } -------------------------------------------------------------------------------- /deficrawler/config/scream-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Scream", 4 | "type": "Lending", 5 | "version": 2, 6 | "chain": "Fantom", 7 | "endpoint": { 8 | "fantom": "https://api.thegraph.com/subgraphs/name/screamsh/scream-v1" 9 | } 10 | }, 11 | "entities": { 12 | "borrow": { 13 | "attributes": { 14 | "tx_id": [ 15 | "id" 16 | ], 17 | "user": [ 18 | "borrower" 19 | ], 20 | "token": [ 21 | "underlyingSymbol" 22 | ], 23 | "amount": [ 24 | "amount" 25 | ], 26 | "timestamp": [ 27 | "blockTime" 28 | ] 29 | }, 30 | "query": { 31 | "extra_fields": {}, 32 | "name": "borrowEvents", 33 | "params": { 34 | "orderBy": "blockTime", 35 | "user":"borrower" 36 | } 37 | }, 38 | "transformations": { 39 | "tx_id": "tx_id_hyphen" 40 | } 41 | }, 42 | "deposit": { 43 | "attributes": { 44 | "tx_id": [ 45 | "id" 46 | ], 47 | "user": [ 48 | "to" 49 | ], 50 | "token": [ 51 | "cTokenSymbol" 52 | ], 53 | "amount": [ 54 | "underlyingAmount" 55 | ], 56 | "timestamp": [ 57 | "blockTime" 58 | ] 59 | }, 60 | "query": { 61 | "name": "mintEvents", 62 | "extra_fields": {}, 63 | "params": { 64 | "orderBy": "blockTime", 65 | "user":"to" 66 | } 67 | }, 68 | "transformations": { 69 | "token": "remove_token_prefix", 70 | "tx_id": "tx_id_hyphen" 71 | } 72 | }, 73 | "liquidation": { 74 | "attributes": { 75 | "tx_id": [ 76 | "id" 77 | ], 78 | "user": [ 79 | "from" 80 | ], 81 | "token_principal": [ 82 | "underlyingSymbol" 83 | ], 84 | "token_collateral": [ 85 | "cTokenSymbol" 86 | ], 87 | "amount_principal": [ 88 | "underlyingRepayAmount" 89 | ], 90 | "amount_collateral": [ 91 | "amount" 92 | ], 93 | "liquidator": [ 94 | "to" 95 | ], 96 | "timestamp": [ 97 | "blockTime" 98 | ] 99 | }, 100 | "query": { 101 | "extra_fields": {}, 102 | "name": "liquidationEvents", 103 | "params": { 104 | "orderBy": "blockTime", 105 | "user":"from" 106 | } 107 | }, 108 | "transformations": { 109 | "tx_id": "tx_id_hyphen" 110 | } 111 | }, 112 | "repay": { 113 | "attributes": { 114 | "tx_id": [ 115 | "id" 116 | ], 117 | "user": [ 118 | "payer" 119 | ], 120 | "token": [ 121 | "underlyingSymbol" 122 | ], 123 | "amount": [ 124 | "amount" 125 | ], 126 | "timestamp": [ 127 | "blockTime" 128 | ] 129 | }, 130 | "query": { 131 | "name": "repayEvents", 132 | "extra_fields": {}, 133 | "params": { 134 | "orderBy": "blockTime", 135 | "user":"payer" 136 | } 137 | }, 138 | "transformations": { 139 | "tx_id": "tx_id_hyphen" 140 | } 141 | }, 142 | "redeem": { 143 | "attributes": { 144 | "tx_id": [ 145 | "id" 146 | ], 147 | "user": [ 148 | "to" 149 | ], 150 | "token": [ 151 | "cTokenSymbol" 152 | ], 153 | "amount": [ 154 | "underlyingAmount" 155 | ], 156 | "timestamp": [ 157 | "blockTime" 158 | ] 159 | }, 160 | "query": { 161 | "name": "redeemEvents", 162 | "extra_fields": {}, 163 | "params": { 164 | "orderBy": "blockTime", 165 | "user":"to" 166 | } 167 | }, 168 | "transformations": { 169 | "tx_id": "tx_id_hyphen" 170 | } 171 | }, 172 | "token": { 173 | "attributes": { 174 | "id": [ 175 | "id" 176 | ], 177 | "symbol": [ 178 | "underlyingSymbol" 179 | ] 180 | }, 181 | "query": { 182 | "name": "markets", 183 | "extra_fields": {}, 184 | "params": { 185 | "orderBy": "id", 186 | "initial_value": "0" 187 | } 188 | }, 189 | "transformations": {} 190 | }, 191 | "user": { 192 | "attributes": { 193 | "user_id": [ 194 | "id" 195 | ], 196 | "active_loans": [ 197 | "tokens", 198 | "totalUnderlyingBorrowed" 199 | ], 200 | "liquidations_count": [ 201 | "countLiquidated" 202 | ] 203 | }, 204 | "query": { 205 | "name": "accounts", 206 | "extra_fields": {}, 207 | "params": { 208 | "orderBy": "id", 209 | "initial_value": "0" 210 | } 211 | }, 212 | "transformations": { 213 | "active_loans": "array_length" 214 | } 215 | }, 216 | "user_position": { 217 | "attributes": { 218 | "user_id": [ 219 | "account", 220 | "id" 221 | ], 222 | "symbol": [ 223 | "symbol" 224 | ], 225 | "debt_amount": [ 226 | "totalUnderlyingBorrowed" 227 | ], 228 | "collateral_amount": [ 229 | "totalUnderlyingSupplied" 230 | ] 231 | }, 232 | "query": { 233 | "name": "accountCTokens", 234 | "extra_fields": {}, 235 | "params": { 236 | "user": "account" 237 | } 238 | }, 239 | "transformations": {} 240 | }, 241 | "rates": { 242 | "attributes": { 243 | "token": [ 244 | "underlyingSymbol" 245 | ], 246 | "variable_borrow_rate": [ 247 | "borrowRate" 248 | ], 249 | "stable_borrow_rate": [ 250 | "borrowRate" 251 | ], 252 | "supply_rate": [ 253 | "supplyRate" 254 | ], 255 | "timestamp": [ 256 | "blockTimestamp" 257 | ] 258 | }, 259 | "query": { 260 | "name": "markets", 261 | "extra_fields": {}, 262 | "params": { 263 | "orderBy": "blockTimestamp", 264 | "asset": "id", 265 | "block": true 266 | } 267 | }, 268 | "transformations": { 269 | "variable_borrow_rate": "rates_units_comp", 270 | "stable_borrow_rate": "rates_na", 271 | "supply_rate": "rates_units_comp" 272 | } 273 | }, 274 | "prices": { 275 | "attributes": { 276 | "id": [ 277 | "id" 278 | ], 279 | "symbol": [ 280 | "symbol" 281 | ], 282 | "underlyingAsset": [ 283 | "underlyingSymbol" 284 | ], 285 | "priceInETH": [ 286 | "underlyingPrice" 287 | ], 288 | "priceInUsd": [ 289 | "underlyingPriceUSD" 290 | ], 291 | "exchangeRate": [ 292 | "exchangeRate" 293 | ], 294 | "timestamp": [ 295 | "blockTimestamp" 296 | ] 297 | }, 298 | "query": { 299 | "name": "markets", 300 | "extra_fields": { 301 | }, 302 | "params": { 303 | "orderBy": "blockTimestamp", 304 | "block": "block" 305 | } 306 | }, 307 | "transformations": { 308 | } 309 | } 310 | } 311 | } -------------------------------------------------------------------------------- /deficrawler/config/sushiswap-1-ethereum.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Sushiswap", 4 | "type": "Descentralized Exchange", 5 | "version": 1, 6 | "chain": "Ethereum", 7 | "endpoint": { 8 | "ethereum": "https://api.thegraph.com/subgraphs/name/croco-finance/sushiswap", 9 | "bsc": "https://api.thegraph.com/subgraphs/name/sushiswap/bsc-exchange", 10 | "polygon": "https://api.thegraph.com/subgraphs/name/sushiswap/matic-exchange", 11 | "fantom": "https://api.thegraph.com/subgraphs/name/sushiswap/fantom-exchange", 12 | "celo": "https://api.thegraph.com/subgraphs/name/sushiswap/celo-exchange" 13 | } 14 | }, 15 | "entities": { 16 | "swap": { 17 | "attributes": { 18 | "user": [ 19 | "sender" 20 | ], 21 | "tx_id": [ 22 | "transaction", 23 | "id" 24 | ], 25 | "from_token": [ 26 | [ 27 | "pair", 28 | "token0", 29 | "symbol" 30 | ], 31 | [ 32 | "pair", 33 | "token1", 34 | "symbol" 35 | ] 36 | ], 37 | "to_token": [ 38 | [ 39 | "pair", 40 | "token0", 41 | "symbol" 42 | ], 43 | [ 44 | "pair", 45 | "token1", 46 | "symbol" 47 | ] 48 | ], 49 | "from_token_amount": [ 50 | [ 51 | "amount0In" 52 | ], 53 | [ 54 | "amount1In" 55 | ] 56 | ], 57 | "to_token_amount": [ 58 | [ 59 | "amount0Out" 60 | ], 61 | [ 62 | "amount1Out" 63 | ] 64 | ], 65 | "pool": [ 66 | "pair", 67 | "id" 68 | ], 69 | "amount_usd": [ 70 | "amountUSD" 71 | ], 72 | "timestamp": [ 73 | "timestamp" 74 | ] 75 | }, 76 | "query": { 77 | "name": "swaps", 78 | "extra_fields": {}, 79 | "params": { 80 | "orderBy": "timestamp", 81 | "pool": "pair" 82 | } 83 | }, 84 | "transformations": { 85 | "from_token": "from_token", 86 | "to_token": "to_token", 87 | "from_token_amount": "from_token_amount", 88 | "to_token_amount": "to_token_amount" 89 | } 90 | }, 91 | "pool": { 92 | "attributes": { 93 | "id": [ 94 | "id" 95 | ], 96 | "pool_tokens": [ 97 | [ 98 | "token0", 99 | "symbol" 100 | ], 101 | [ 102 | "token1", 103 | "symbol" 104 | ] 105 | ], 106 | "created_at": [ 107 | "createdAtTimestamp" 108 | ], 109 | "liquidity_usd": [ 110 | "reserveUSD" 111 | ] 112 | }, 113 | "query": { 114 | "name": "pairs", 115 | "extra_fields": {}, 116 | "params": { 117 | "orderBy": "id", 118 | "initial_value": "0" 119 | } 120 | }, 121 | "transformations": { 122 | "pool_tokens": "concat_symbols" 123 | } 124 | }, 125 | "mint": { 126 | "attributes": { 127 | "tx_id": [ 128 | "transaction", 129 | "id" 130 | ], 131 | "token0": [ 132 | "pair", 133 | "token0", 134 | "symbol" 135 | ], 136 | "token1": [ 137 | "pair", 138 | "token1", 139 | "symbol" 140 | ], 141 | "amount0": [ 142 | "amount0" 143 | ], 144 | "amount1": [ 145 | "amount1" 146 | ], 147 | "user": [ 148 | "to" 149 | ], 150 | "pool": [ 151 | "pair", 152 | "id" 153 | ], 154 | "timestamp": [ 155 | "timestamp" 156 | ] 157 | }, 158 | "query": { 159 | "name": "mints", 160 | "extra_fields": {}, 161 | "params": { 162 | "orderBy": "timestamp" 163 | } 164 | }, 165 | "transformations": {} 166 | }, 167 | "burn": { 168 | "attributes": { 169 | "tx_id": [ 170 | "transaction", 171 | "id" 172 | ], 173 | "token0": [ 174 | "pair", 175 | "token0", 176 | "symbol" 177 | ], 178 | "token1": [ 179 | "pair", 180 | "token1", 181 | "symbol" 182 | ], 183 | "amount0": [ 184 | "amount0" 185 | ], 186 | "amount1": [ 187 | "amount1" 188 | ], 189 | "user": [ 190 | "sender" 191 | ], 192 | "pool": [ 193 | "pair", 194 | "id" 195 | ], 196 | "timestamp": [ 197 | "timestamp" 198 | ] 199 | }, 200 | "query": { 201 | "name": "burns", 202 | "extra_fields": {}, 203 | "params": { 204 | "orderBy": "timestamp" 205 | } 206 | }, 207 | "transformations": {} 208 | }, 209 | "pool_volume_hourly": { 210 | "attributes": { 211 | "id": [ 212 | "pair", 213 | "id" 214 | ], 215 | "token0": [ 216 | "reserve0" 217 | ], 218 | "token1": [ 219 | "reserve1" 220 | ], 221 | "liquidity": [ 222 | "reserveUSD" 223 | ], 224 | "hourlyVolumeUSD": [ 225 | "hourlyVolumeUSD" 226 | ], 227 | "hourlyVolumeToken0": [ 228 | "hourlyVolumeToken0" 229 | ], 230 | "hourlyVolumeToken1": [ 231 | "hourlyVolumeToken1" 232 | ], 233 | "hourlyTxns": [ 234 | "hourlyTxns" 235 | ], 236 | "hourStartUnix": [ 237 | "hourStartUnix" 238 | ] 239 | }, 240 | "query": { 241 | "name": "pairHourDatas", 242 | "extra_fields": {}, 243 | "params": { 244 | "orderBy": "hourStartUnix", 245 | "pool": "pair" 246 | } 247 | }, 248 | "transformations": {} 249 | } 250 | } 251 | } -------------------------------------------------------------------------------- /deficrawler/config/sushiswap-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Sushiswap", 4 | "type": "Descentralized Exchange", 5 | "version": 1, 6 | "chain": "Ethereum", 7 | "endpoint": { 8 | "ethereum": "https://api.thegraph.com/subgraphs/name/croco-finance/sushiswap", 9 | "bsc": "https://api.thegraph.com/subgraphs/name/sushiswap/bsc-exchange", 10 | "polygon": "https://api.thegraph.com/subgraphs/name/sushiswap/matic-exchange", 11 | "fantom": "https://api.thegraph.com/subgraphs/name/sushiswap/fantom-exchange", 12 | "celo": "https://api.thegraph.com/subgraphs/name/sushiswap/celo-exchange" 13 | } 14 | }, 15 | "entities": { 16 | "swap": { 17 | "attributes": { 18 | "user": [ 19 | "sender" 20 | ], 21 | "tx_id": [ 22 | "transaction", 23 | "id" 24 | ], 25 | "from_token": [ 26 | [ 27 | "pair", 28 | "token0", 29 | "symbol" 30 | ], 31 | [ 32 | "pair", 33 | "token1", 34 | "symbol" 35 | ] 36 | ], 37 | "to_token": [ 38 | [ 39 | "pair", 40 | "token0", 41 | "symbol" 42 | ], 43 | [ 44 | "pair", 45 | "token1", 46 | "symbol" 47 | ] 48 | ], 49 | "from_token_amount": [ 50 | [ 51 | "amount0In" 52 | ], 53 | [ 54 | "amount1In" 55 | ] 56 | ], 57 | "to_token_amount": [ 58 | [ 59 | "amount0Out" 60 | ], 61 | [ 62 | "amount1Out" 63 | ] 64 | ], 65 | "pool": [ 66 | "pair", 67 | "id" 68 | ], 69 | "amount_usd": [ 70 | "amountUSD" 71 | ], 72 | "timestamp": [ 73 | "timestamp" 74 | ] 75 | }, 76 | "query": { 77 | "name": "swaps", 78 | "extra_fields": {}, 79 | "params": { 80 | "orderBy": "timestamp", 81 | "pool": "pair" 82 | } 83 | }, 84 | "transformations": { 85 | "from_token": "from_token", 86 | "to_token": "to_token", 87 | "from_token_amount": "from_token_amount", 88 | "to_token_amount": "to_token_amount" 89 | } 90 | }, 91 | "pool": { 92 | "attributes": { 93 | "id": [ 94 | "id" 95 | ], 96 | "pool_tokens": [ 97 | [ 98 | "token0", 99 | "symbol" 100 | ], 101 | [ 102 | "token1", 103 | "symbol" 104 | ] 105 | ], 106 | "created_at":[ 107 | "timestamp" 108 | ], 109 | "liquidity_usd": [ 110 | "reserveUSD" 111 | ] 112 | }, 113 | "query": { 114 | "name": "pairs", 115 | "extra_fields": {}, 116 | "params": { 117 | "orderBy": "id", 118 | "initial_value": "0" 119 | } 120 | }, 121 | "transformations": { 122 | "pool_tokens": "concat_symbols" 123 | } 124 | }, 125 | "mint": { 126 | "attributes": { 127 | "tx_id": [ 128 | "transaction", 129 | "id" 130 | ], 131 | "token0": [ 132 | "pair", 133 | "token0", 134 | "symbol" 135 | ], 136 | "token1": [ 137 | "pair", 138 | "token1", 139 | "symbol" 140 | ], 141 | "amount0": [ 142 | "amount0" 143 | ], 144 | "amount1": [ 145 | "amount1" 146 | ], 147 | "user": [ 148 | "to" 149 | ], 150 | "pool": [ 151 | "pair", 152 | "id" 153 | ], 154 | "timestamp": [ 155 | "timestamp" 156 | ] 157 | }, 158 | "query": { 159 | "name": "mints", 160 | "extra_fields": {}, 161 | "params": { 162 | "orderBy": "timestamp" 163 | } 164 | }, 165 | "transformations": {} 166 | }, 167 | "burn": { 168 | "attributes": { 169 | "tx_id": [ 170 | "transaction", 171 | "id" 172 | ], 173 | "token0": [ 174 | "pair", 175 | "token0", 176 | "symbol" 177 | ], 178 | "token1": [ 179 | "pair", 180 | "token1", 181 | "symbol" 182 | ], 183 | "amount0": [ 184 | "amount0" 185 | ], 186 | "amount1": [ 187 | "amount1" 188 | ], 189 | "user": [ 190 | "sender" 191 | ], 192 | "pool": [ 193 | "pair", 194 | "id" 195 | ], 196 | "timestamp": [ 197 | "timestamp" 198 | ] 199 | }, 200 | "query": { 201 | "name": "burns", 202 | "extra_fields": {}, 203 | "params": { 204 | "orderBy": "timestamp" 205 | } 206 | }, 207 | "transformations": {} 208 | }, 209 | "pool_volume_hourly": { 210 | "attributes": { 211 | "id": [ 212 | "pair", 213 | "id" 214 | ], 215 | "token0":[ 216 | "reserve0" 217 | ], 218 | "token1":[ 219 | "reserve1" 220 | ], 221 | "liquidity":[ 222 | "reserveUSD" 223 | ], 224 | "hourlyVolumeUSD":[ 225 | "volumeUSD" 226 | ], 227 | "hourlyVolumeToken0":[ 228 | "volumeToken0" 229 | ], 230 | "hourlyVolumeToken1":[ 231 | "volumeToken1" 232 | ], 233 | "hourlyTxns":[ 234 | "txCount" 235 | ], 236 | "hourStartUnix": [ 237 | "date" 238 | ] 239 | }, 240 | "query": { 241 | "name": "pairHourDatas", 242 | "extra_fields": {}, 243 | "params": { 244 | "orderBy": "date", 245 | "pool": "pair" 246 | } 247 | }, 248 | "transformations": { 249 | } 250 | } 251 | } 252 | } -------------------------------------------------------------------------------- /deficrawler/config/traderjoe-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Trader Joe", 4 | "type": "Descentralized Exchange", 5 | "version": 2, 6 | "endpoint": { 7 | "avalanche": "https://api.thegraph.com/subgraphs/name/token-terminal/trader-joe-v1-avalanche" 8 | } 9 | }, 10 | "entities": { 11 | "swap": { 12 | "attributes": { 13 | "user": [ 14 | "sender" 15 | ], 16 | "tx_id": [ 17 | "transaction", 18 | "id" 19 | ], 20 | "from_token": [ 21 | [ 22 | "pair", 23 | "token0", 24 | "symbol" 25 | ], 26 | [ 27 | "pair", 28 | "token1", 29 | "symbol" 30 | ] 31 | ], 32 | "to_token": [ 33 | [ 34 | "pair", 35 | "token0", 36 | "symbol" 37 | ], 38 | [ 39 | "pair", 40 | "token1", 41 | "symbol" 42 | ] 43 | ], 44 | "from_token_amount": [ 45 | [ 46 | "amount0In" 47 | ], 48 | [ 49 | "amount1In" 50 | ] 51 | ], 52 | "to_token_amount": [ 53 | [ 54 | "amount0Out" 55 | ], 56 | [ 57 | "amount1Out" 58 | ] 59 | ], 60 | "pool": [ 61 | "pair", 62 | "id" 63 | ], 64 | "amount_usd": [ 65 | "amountUSD" 66 | ], 67 | "timestamp": [ 68 | "timestamp" 69 | ] 70 | }, 71 | "query": { 72 | "name": "swaps", 73 | "extra_fields": {}, 74 | "params": { 75 | "orderBy": "timestamp", 76 | "pool": "pair" 77 | } 78 | }, 79 | "transformations": { 80 | "from_token": "from_token", 81 | "to_token": "to_token", 82 | "from_token_amount": "from_token_amount", 83 | "to_token_amount": "to_token_amount" 84 | } 85 | }, 86 | "pool": { 87 | "attributes": { 88 | "id": [ 89 | "id" 90 | ], 91 | "pool_tokens": [ 92 | [ 93 | "token0", 94 | "symbol" 95 | ], 96 | [ 97 | "token1", 98 | "symbol" 99 | ] 100 | ], 101 | "created_at": [ 102 | "timestamp" 103 | ], 104 | "liquidity_usd": [ 105 | "reserveUSD" 106 | ] 107 | }, 108 | "query": { 109 | "name": "pairs", 110 | "extra_fields": {}, 111 | "params": { 112 | "orderBy": "id", 113 | "initial_value": "0" 114 | } 115 | }, 116 | "transformations": { 117 | "pool_tokens": "concat_symbols" 118 | } 119 | }, 120 | "mint": { 121 | "attributes": { 122 | "tx_id": [ 123 | "transaction", 124 | "id" 125 | ], 126 | "token0": [ 127 | "pair", 128 | "token0", 129 | "symbol" 130 | ], 131 | "token1": [ 132 | "pair", 133 | "token1", 134 | "symbol" 135 | ], 136 | "amount0": [ 137 | "amount0" 138 | ], 139 | "amount1": [ 140 | "amount1" 141 | ], 142 | "user": [ 143 | "to" 144 | ], 145 | "pool": [ 146 | "pair", 147 | "id" 148 | ], 149 | "timestamp": [ 150 | "timestamp" 151 | ] 152 | }, 153 | "query": { 154 | "name": "mints", 155 | "extra_fields": {}, 156 | "params": { 157 | "orderBy": "timestamp" 158 | } 159 | }, 160 | "transformations": {} 161 | }, 162 | "burn": { 163 | "attributes": { 164 | "tx_id": [ 165 | "transaction", 166 | "id" 167 | ], 168 | "token0": [ 169 | "pair", 170 | "token0", 171 | "symbol" 172 | ], 173 | "token1": [ 174 | "pair", 175 | "token1", 176 | "symbol" 177 | ], 178 | "amount0": [ 179 | "amount0" 180 | ], 181 | "amount1": [ 182 | "amount1" 183 | ], 184 | "user": [ 185 | "sender" 186 | ], 187 | "pool": [ 188 | "pair", 189 | "id" 190 | ], 191 | "timestamp": [ 192 | "timestamp" 193 | ] 194 | }, 195 | "query": { 196 | "name": "burns", 197 | "extra_fields": {}, 198 | "params": { 199 | "orderBy": "timestamp" 200 | } 201 | }, 202 | "transformations": {} 203 | } 204 | } 205 | } -------------------------------------------------------------------------------- /deficrawler/config/ubeswap-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Ubeswap", 4 | "type": "Descentralized Exchange", 5 | "version": 1, 6 | "chain": "Celo", 7 | "endpoint": { 8 | "celo": "https://api.thegraph.com/subgraphs/name/ubeswap/ubeswap" 9 | } 10 | }, 11 | "entities": { 12 | "swap": { 13 | "attributes": { 14 | "user": [ 15 | "sender" 16 | ], 17 | "tx_id": [ 18 | "transaction", 19 | "id" 20 | ], 21 | "from_token": [ 22 | [ 23 | "pair", 24 | "token0", 25 | "symbol" 26 | ], 27 | [ 28 | "pair", 29 | "token1", 30 | "symbol" 31 | ] 32 | ], 33 | "to_token": [ 34 | [ 35 | "pair", 36 | "token0", 37 | "symbol" 38 | ], 39 | [ 40 | "pair", 41 | "token1", 42 | "symbol" 43 | ] 44 | ], 45 | "from_token_amount": [ 46 | [ 47 | "amount0In" 48 | ], 49 | [ 50 | "amount1In" 51 | ] 52 | ], 53 | "to_token_amount": [ 54 | [ 55 | "amount0Out" 56 | ], 57 | [ 58 | "amount1Out" 59 | ] 60 | ], 61 | "pool": [ 62 | "pair", 63 | "id" 64 | ], 65 | "amount_usd": [ 66 | "amountUSD" 67 | ], 68 | "timestamp": [ 69 | "timestamp" 70 | ] 71 | }, 72 | "query": { 73 | "name": "swaps", 74 | "extra_fields": {}, 75 | "params": { 76 | "orderBy": "timestamp", 77 | "pool": "pair" 78 | } 79 | }, 80 | "transformations": { 81 | "from_token": "from_token", 82 | "to_token": "to_token", 83 | "from_token_amount": "from_token_amount", 84 | "to_token_amount": "to_token_amount" 85 | } 86 | }, 87 | "pool": { 88 | "attributes": { 89 | "id": [ 90 | "id" 91 | ], 92 | "pool_tokens": [ 93 | [ 94 | "token0", 95 | "symbol" 96 | ], 97 | [ 98 | "token1", 99 | "symbol" 100 | ] 101 | ], 102 | "created_at": [ 103 | "createdAtTimestamp" 104 | ], 105 | "liquidity_usd": [ 106 | "reserveUSD" 107 | ] 108 | }, 109 | "query": { 110 | "name": "pairs", 111 | "extra_fields": {}, 112 | "params": { 113 | "orderBy": "id", 114 | "initial_value": "0" 115 | } 116 | }, 117 | "transformations": { 118 | "pool_tokens": "concat_symbols" 119 | } 120 | }, 121 | "mint": { 122 | "attributes": { 123 | "tx_id": [ 124 | "transaction", 125 | "id" 126 | ], 127 | "token0": [ 128 | "pair", 129 | "token0", 130 | "symbol" 131 | ], 132 | "token1": [ 133 | "pair", 134 | "token1", 135 | "symbol" 136 | ], 137 | "amount0": [ 138 | "amount0" 139 | ], 140 | "amount1": [ 141 | "amount1" 142 | ], 143 | "user": [ 144 | "to" 145 | ], 146 | "pool": [ 147 | "pair", 148 | "id" 149 | ], 150 | "timestamp": [ 151 | "timestamp" 152 | ] 153 | }, 154 | "query": { 155 | "name": "mints", 156 | "extra_fields": {}, 157 | "params": { 158 | "orderBy": "timestamp" 159 | } 160 | }, 161 | "transformations": {} 162 | }, 163 | "burn": { 164 | "attributes": { 165 | "tx_id": [ 166 | "transaction", 167 | "id" 168 | ], 169 | "token0": [ 170 | "pair", 171 | "token0", 172 | "symbol" 173 | ], 174 | "token1": [ 175 | "pair", 176 | "token1", 177 | "symbol" 178 | ], 179 | "amount0": [ 180 | "amount0" 181 | ], 182 | "amount1": [ 183 | "amount1" 184 | ], 185 | "user": [ 186 | "sender" 187 | ], 188 | "pool": [ 189 | "pair", 190 | "id" 191 | ], 192 | "timestamp": [ 193 | "timestamp" 194 | ] 195 | }, 196 | "query": { 197 | "name": "burns", 198 | "extra_fields": {}, 199 | "params": { 200 | "orderBy": "timestamp" 201 | } 202 | }, 203 | "transformations": {} 204 | }, 205 | "pool_volume_hourly": { 206 | "attributes": { 207 | "id": [ 208 | "pair", 209 | "id" 210 | ], 211 | "token0": [ 212 | "reserve0" 213 | ], 214 | "token1": [ 215 | "reserve1" 216 | ], 217 | "liquidity": [ 218 | "reserveUSD" 219 | ], 220 | "hourlyVolumeUSD": [ 221 | "hourlyVolumeUSD" 222 | ], 223 | "hourlyVolumeToken0": [ 224 | "hourlyVolumeToken0" 225 | ], 226 | "hourlyVolumeToken1": [ 227 | "hourlyVolumeToken1" 228 | ], 229 | "hourlyTxns": [ 230 | "hourlyTxns" 231 | ], 232 | "hourStartUnix": [ 233 | "hourStartUnix" 234 | ] 235 | }, 236 | "query": { 237 | "name": "pairHourDatas", 238 | "extra_fields": {}, 239 | "params": { 240 | "orderBy": "hourStartUnix", 241 | "pool": "pair" 242 | } 243 | }, 244 | "transformations": {} 245 | } 246 | } 247 | } -------------------------------------------------------------------------------- /deficrawler/config/uniswap-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Uniswap", 4 | "type": "Descentralized Exchange", 5 | "version": 2, 6 | "chain": "Ethereum", 7 | "endpoint": { 8 | "ethereum": "https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2" 9 | } 10 | }, 11 | "entities": { 12 | "swap": { 13 | "attributes": { 14 | "user": [ 15 | "sender" 16 | ], 17 | "tx_id": [ 18 | "transaction", 19 | "id" 20 | ], 21 | "from_token": [ 22 | [ 23 | "pair", 24 | "token0", 25 | "symbol" 26 | ], 27 | [ 28 | "pair", 29 | "token1", 30 | "symbol" 31 | ] 32 | ], 33 | "to_token": [ 34 | [ 35 | "pair", 36 | "token0", 37 | "symbol" 38 | ], 39 | [ 40 | "pair", 41 | "token1", 42 | "symbol" 43 | ] 44 | ], 45 | "from_token_amount": [ 46 | [ 47 | "amount0In" 48 | ], 49 | [ 50 | "amount1In" 51 | ] 52 | ], 53 | "to_token_amount": [ 54 | [ 55 | "amount0Out" 56 | ], 57 | [ 58 | "amount1Out" 59 | ] 60 | ], 61 | "pool": [ 62 | "pair", 63 | "id" 64 | ], 65 | "amount_usd": [ 66 | "amountUSD" 67 | ], 68 | "timestamp": [ 69 | "timestamp" 70 | ] 71 | }, 72 | "query": { 73 | "name": "swaps", 74 | "extra_fields": {}, 75 | "params": { 76 | "orderBy": "timestamp", 77 | "pool": "pair" 78 | } 79 | }, 80 | "transformations": { 81 | "from_token": "from_token", 82 | "to_token": "to_token", 83 | "from_token_amount": "from_token_amount", 84 | "to_token_amount": "to_token_amount" 85 | } 86 | }, 87 | "pool": { 88 | "attributes": { 89 | "id": [ 90 | "id" 91 | ], 92 | "pool_tokens": [ 93 | [ 94 | "token0", 95 | "symbol" 96 | ], 97 | [ 98 | "token1", 99 | "symbol" 100 | ] 101 | ], 102 | "created_at":[ 103 | "createdAtTimestamp" 104 | ], 105 | "liquidity_usd": [ 106 | "reserveUSD" 107 | ] 108 | }, 109 | "query": { 110 | "name": "pairs", 111 | "extra_fields": {}, 112 | "params": { 113 | "orderBy": "id", 114 | "initial_value": "0" 115 | } 116 | }, 117 | "transformations": { 118 | "pool_tokens": "concat_symbols" 119 | } 120 | }, 121 | "mint": { 122 | "attributes": { 123 | "tx_id": [ 124 | "transaction", 125 | "id" 126 | ], 127 | "token0": [ 128 | "pair", 129 | "token0", 130 | "symbol" 131 | ], 132 | "token1": [ 133 | "pair", 134 | "token1", 135 | "symbol" 136 | ], 137 | "amount0": [ 138 | "amount0" 139 | ], 140 | "amount1": [ 141 | "amount1" 142 | ], 143 | "user": [ 144 | "to" 145 | ], 146 | "pool": [ 147 | "pair", 148 | "id" 149 | ], 150 | "timestamp": [ 151 | "timestamp" 152 | ] 153 | }, 154 | "query": { 155 | "name": "mints", 156 | "extra_fields": {}, 157 | "params": { 158 | "orderBy": "timestamp" 159 | } 160 | }, 161 | "transformations": {} 162 | }, 163 | "burn": { 164 | "attributes": { 165 | "tx_id": [ 166 | "transaction", 167 | "id" 168 | ], 169 | "token0": [ 170 | "pair", 171 | "token0", 172 | "symbol" 173 | ], 174 | "token1": [ 175 | "pair", 176 | "token1", 177 | "symbol" 178 | ], 179 | "amount0": [ 180 | "amount0" 181 | ], 182 | "amount1": [ 183 | "amount1" 184 | ], 185 | "user": [ 186 | "sender" 187 | ], 188 | "pool": [ 189 | "pair", 190 | "id" 191 | ], 192 | "timestamp": [ 193 | "timestamp" 194 | ] 195 | }, 196 | "query": { 197 | "name": "burns", 198 | "extra_fields": {}, 199 | "params": { 200 | "orderBy": "timestamp" 201 | } 202 | }, 203 | "transformations": {} 204 | }, 205 | "pool_volume_hourly": { 206 | "attributes": { 207 | "id": [ 208 | "pair", 209 | "id" 210 | ], 211 | "token0":[ 212 | "reserve0" 213 | ], 214 | "token1":[ 215 | "reserve1" 216 | ], 217 | "liquidity":[ 218 | "reserveUSD" 219 | ], 220 | "hourlyVolumeUSD":[ 221 | "hourlyVolumeUSD" 222 | ], 223 | "hourlyVolumeToken0":[ 224 | "hourlyVolumeToken0" 225 | ], 226 | "hourlyVolumeToken1":[ 227 | "hourlyVolumeToken1" 228 | ], 229 | "hourlyTxns":[ 230 | "hourlyTxns" 231 | ], 232 | "hourStartUnix": [ 233 | "hourStartUnix" 234 | ] 235 | }, 236 | "query": { 237 | "name": "pairHourDatas", 238 | "extra_fields": {}, 239 | "params": { 240 | "orderBy": "hourStartUnix", 241 | "pool": "pair" 242 | } 243 | }, 244 | "transformations": { 245 | } 246 | } 247 | } 248 | } -------------------------------------------------------------------------------- /deficrawler/config/uniswap-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Uniswap", 4 | "type": "Descentralized Exchange", 5 | "version": 3, 6 | "chain": "Ethereum", 7 | "endpoint": { 8 | "ethereum": "https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3", 9 | "optimism": "https://api.thegraph.com/subgraphs/name/storres93/uniswap-v3-optimism", 10 | "polygon": "https://api.thegraph.com/subgraphs/name/kalinbas/uniswap-v3-polygon" 11 | } 12 | }, 13 | "entities": { 14 | "swap": { 15 | "attributes": { 16 | "user": [ 17 | "sender" 18 | ], 19 | "tx_id": [ 20 | "transaction", 21 | "id" 22 | ], 23 | "from_token": [ 24 | [ 25 | "token0", 26 | "symbol" 27 | ], 28 | [ 29 | "token1", 30 | "symbol" 31 | ] 32 | ], 33 | "to_token": [ 34 | [ 35 | "token0", 36 | "symbol" 37 | ], 38 | [ 39 | "token1", 40 | "symbol" 41 | ] 42 | ], 43 | "from_token_amount": [ 44 | [ 45 | "amount0" 46 | ], 47 | [ 48 | "amount1" 49 | ] 50 | ], 51 | "to_token_amount": [ 52 | [ 53 | "amount0" 54 | ], 55 | [ 56 | "amount1" 57 | ] 58 | ], 59 | "pool": [ 60 | "pool", 61 | "id" 62 | ], 63 | "amount_usd": [ 64 | "amountUSD" 65 | ], 66 | "timestamp": [ 67 | "timestamp" 68 | ] 69 | }, 70 | "query": { 71 | "name": "swaps", 72 | "extra_fields": {}, 73 | "params": { 74 | "orderBy": "timestamp", 75 | "pool": "pair" 76 | } 77 | }, 78 | "transformations": { 79 | "from_token": "from_token_v3", 80 | "to_token": "to_token_v3", 81 | "from_token_amount": "from_token_amount_v3", 82 | "to_token_amount": "to_token_amount_v3" 83 | } 84 | }, 85 | "mint": { 86 | "attributes": { 87 | "tx_id": [ 88 | "transaction", 89 | "id" 90 | ], 91 | "token0": [ 92 | "token0", 93 | "symbol" 94 | ], 95 | "token1": [ 96 | "token1", 97 | "symbol" 98 | ], 99 | "amount0": [ 100 | "amount0" 101 | ], 102 | "amount1": [ 103 | "amount1" 104 | ], 105 | "user": [ 106 | "owner" 107 | ], 108 | "pool": [ 109 | "pool", 110 | "id" 111 | ], 112 | "timestamp": [ 113 | "timestamp" 114 | ] 115 | }, 116 | "query": { 117 | "name": "mints", 118 | "extra_fields": {}, 119 | "params": { 120 | "orderBy": "timestamp" 121 | } 122 | }, 123 | "transformations": {} 124 | }, 125 | "burn": { 126 | "attributes": { 127 | "tx_id": [ 128 | "transaction", 129 | "id" 130 | ], 131 | "token0": [ 132 | "token0", 133 | "symbol" 134 | ], 135 | "token1": [ 136 | "token1", 137 | "symbol" 138 | ], 139 | "amount0": [ 140 | "amount0" 141 | ], 142 | "amount1": [ 143 | "amount1" 144 | ], 145 | "user": [ 146 | "owner" 147 | ], 148 | "pool": [ 149 | "pool", 150 | "id" 151 | ], 152 | "timestamp": [ 153 | "timestamp" 154 | ] 155 | }, 156 | "query": { 157 | "name": "burns", 158 | "extra_fields": {}, 159 | "params": { 160 | "orderBy": "timestamp" 161 | } 162 | }, 163 | "transformations": {} 164 | }, 165 | "pool": { 166 | "attributes": { 167 | "id": [ 168 | "id" 169 | ], 170 | "pool_tokens": [ 171 | [ 172 | "token0", 173 | "symbol" 174 | ], 175 | [ 176 | "token1", 177 | "symbol" 178 | ] 179 | ], 180 | "created_at": [ 181 | "createdAtTimestamp" 182 | ], 183 | "liquidity_usd": [ 184 | "totalValueLockedUSD" 185 | ] 186 | }, 187 | "query": { 188 | "name": "pools", 189 | "extra_fields": {}, 190 | "params": { 191 | "orderBy": "id", 192 | "initial_value": "0" 193 | } 194 | }, 195 | "transformations": { 196 | "pool_tokens": "concat_symbols" 197 | } 198 | } 199 | } 200 | } -------------------------------------------------------------------------------- /deficrawler/config/venus-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "protocol": { 3 | "name": "Venus", 4 | "type": "Lending", 5 | "version": 1, 6 | "chain": "BSC", 7 | "endpoint": { 8 | "bsc": "https://api.thegraph.com/subgraphs/name/venusprotocol/venus-subgraph" 9 | } 10 | }, 11 | "entities": { 12 | "borrow": { 13 | "attributes": { 14 | "tx_id": [ 15 | "id" 16 | ], 17 | "user": [ 18 | "borrower" 19 | ], 20 | "token": [ 21 | "underlyingSymbol" 22 | ], 23 | "amount": [ 24 | "amount" 25 | ], 26 | "timestamp": [ 27 | "blockTime" 28 | ] 29 | }, 30 | "query": { 31 | "extra_fields": {}, 32 | "name": "borrowEvents", 33 | "params": { 34 | "orderBy": "blockTime", 35 | "user":"borrower" 36 | } 37 | }, 38 | "transformations": { 39 | "tx_id": "tx_id_hyphen" 40 | } 41 | }, 42 | "deposit": { 43 | "attributes": { 44 | "tx_id": [ 45 | "id" 46 | ], 47 | "user": [ 48 | "to" 49 | ], 50 | "token": [ 51 | "vTokenSymbol" 52 | ], 53 | "amount": [ 54 | "underlyingAmount" 55 | ], 56 | "timestamp": [ 57 | "blockTime" 58 | ] 59 | }, 60 | "query": { 61 | "name": "mintEvents", 62 | "extra_fields": {}, 63 | "params": { 64 | "orderBy": "blockTime", 65 | "user":"to" 66 | } 67 | }, 68 | "transformations": { 69 | "token": "remove_token_prefix", 70 | "tx_id": "tx_id_hyphen" 71 | } 72 | }, 73 | "liquidation": { 74 | "attributes": { 75 | "tx_id": [ 76 | "id" 77 | ], 78 | "user": [ 79 | "from" 80 | ], 81 | "token_principal": [ 82 | "underlyingSymbol" 83 | ], 84 | "token_collateral": [ 85 | "vTokenSymbol" 86 | ], 87 | "amount_principal": [ 88 | "underlyingRepayAmount" 89 | ], 90 | "amount_collateral": [ 91 | "amount" 92 | ], 93 | "liquidator": [ 94 | "to" 95 | ], 96 | "timestamp": [ 97 | "blockTime" 98 | ] 99 | }, 100 | "query": { 101 | "extra_fields": {}, 102 | "name": "liquidationEvents", 103 | "params": { 104 | "orderBy": "blockTime", 105 | "user":"from" 106 | } 107 | }, 108 | "transformations": { 109 | "tx_id": "tx_id_hyphen" 110 | } 111 | }, 112 | "repay": { 113 | "attributes": { 114 | "tx_id": [ 115 | "id" 116 | ], 117 | "user": [ 118 | "payer" 119 | ], 120 | "token": [ 121 | "underlyingSymbol" 122 | ], 123 | "amount": [ 124 | "amount" 125 | ], 126 | "timestamp": [ 127 | "blockTime" 128 | ] 129 | }, 130 | "query": { 131 | "name": "repayEvents", 132 | "extra_fields": {}, 133 | "params": { 134 | "orderBy": "blockTime", 135 | "user":"payer" 136 | } 137 | }, 138 | "transformations": { 139 | "tx_id": "tx_id_hyphen" 140 | } 141 | }, 142 | "redeem": { 143 | "attributes": { 144 | "tx_id": [ 145 | "id" 146 | ], 147 | "user": [ 148 | "to" 149 | ], 150 | "token": [ 151 | "vTokenSymbol" 152 | ], 153 | "amount": [ 154 | "underlyingAmount" 155 | ], 156 | "timestamp": [ 157 | "blockTime" 158 | ] 159 | }, 160 | "query": { 161 | "name": "redeemEvents", 162 | "extra_fields": {}, 163 | "params": { 164 | "orderBy": "blockTime", 165 | "user":"to" 166 | } 167 | }, 168 | "transformations": { 169 | "tx_id": "tx_id_hyphen" 170 | } 171 | }, 172 | "token": { 173 | "attributes": { 174 | "id": [ 175 | "id" 176 | ], 177 | "symbol": [ 178 | "underlyingSymbol" 179 | ] 180 | }, 181 | "query": { 182 | "name": "markets", 183 | "extra_fields": {}, 184 | "params": { 185 | "orderBy": "id", 186 | "initial_value": "0" 187 | } 188 | }, 189 | "transformations": {} 190 | }, 191 | "user": { 192 | "attributes": { 193 | "user_id": [ 194 | "id" 195 | ], 196 | "active_loans": [ 197 | "tokens", 198 | "totalUnderlyingBorrowed" 199 | ], 200 | "liquidations_count": [ 201 | "countLiquidated" 202 | ] 203 | }, 204 | "query": { 205 | "name": "accounts", 206 | "extra_fields": {}, 207 | "params": { 208 | "orderBy": "id", 209 | "initial_value": "0" 210 | } 211 | }, 212 | "transformations": { 213 | "active_loans": "array_length" 214 | } 215 | }, 216 | "user_position": { 217 | "attributes": { 218 | "user_id": [ 219 | "account", 220 | "id" 221 | ], 222 | "symbol": [ 223 | "symbol" 224 | ], 225 | "debt_amount": [ 226 | "totalUnderlyingBorrowed" 227 | ], 228 | "collateral_amount": [ 229 | "totalUnderlyingSupplied" 230 | ] 231 | }, 232 | "query": { 233 | "name": "accountCTokens", 234 | "extra_fields": {}, 235 | "params": { 236 | "user": "account" 237 | } 238 | }, 239 | "transformations": {} 240 | }, 241 | "rates": { 242 | "attributes": { 243 | "token": [ 244 | "underlyingSymbol" 245 | ], 246 | "variable_borrow_rate": [ 247 | "borrowRate" 248 | ], 249 | "stable_borrow_rate": [ 250 | "borrowRate" 251 | ], 252 | "supply_rate": [ 253 | "supplyRate" 254 | ], 255 | "timestamp": [ 256 | "blockTimestamp" 257 | ] 258 | }, 259 | "query": { 260 | "name": "markets", 261 | "extra_fields": {}, 262 | "params": { 263 | "orderBy": "blockTimestamp", 264 | "asset": "id", 265 | "block": true 266 | } 267 | }, 268 | "transformations": { 269 | "variable_borrow_rate": "rates_units_comp", 270 | "stable_borrow_rate": "rates_na", 271 | "supply_rate": "rates_units_comp" 272 | } 273 | }, 274 | "prices": { 275 | "attributes": { 276 | "id": [ 277 | "id" 278 | ], 279 | "symbol": [ 280 | "symbol" 281 | ], 282 | "underlyingAsset": [ 283 | "underlyingSymbol" 284 | ], 285 | "priceInETH": [ 286 | "underlyingPrice" 287 | ], 288 | "priceInUsd": [ 289 | "underlyingPriceUSD" 290 | ], 291 | "exchangeRate": [ 292 | "exchangeRate" 293 | ], 294 | "timestamp": [ 295 | "blockTimestamp" 296 | ] 297 | }, 298 | "query": { 299 | "name": "markets", 300 | "extra_fields": { 301 | }, 302 | "params": { 303 | "orderBy": "blockTimestamp", 304 | "block": "block" 305 | } 306 | }, 307 | "transformations": { 308 | } 309 | } 310 | } 311 | } -------------------------------------------------------------------------------- /deficrawler/dex.py: -------------------------------------------------------------------------------- 1 | from deficrawler.protocol_base import ProtocolBase 2 | 3 | from datetime import datetime 4 | 5 | 6 | class Dex(ProtocolBase): 7 | """ 8 | Class to get data for Dexes protocols 9 | """ 10 | 11 | def __init__(self, protocol, chain, version): 12 | super().__init__( 13 | protocol=protocol, 14 | chain=chain, 15 | version=version 16 | ) 17 | self.protocol_type = "dex" 18 | 19 | def get_data_from_date_range(self, from_date, to_date, entity, pool=''): 20 | """ 21 | Gets data for the specified entity in the from_data to to_date period. 22 | The entities are defined in the configuration of each protocol. 23 | """ 24 | 25 | from_timestamp = int( 26 | datetime.strptime(from_date, '%d/%m/%Y %H:%M:%S').timestamp()) 27 | 28 | to_timestamp = int(datetime.strptime( 29 | to_date, '%d/%m/%Y %H:%M:%S').timestamp()) 30 | 31 | config = super().get_protocol_config(entity) 32 | 33 | pool_filter = '' 34 | if(pool != ''): 35 | pool_filter = { 36 | self.mappings_file['entities'][entity]['query']['params']['pool']: pool 37 | } 38 | 39 | response_data = super().query_data_from_date_range( 40 | from_timestamp=from_timestamp, 41 | to_timestamp=to_timestamp, 42 | entity=entity, 43 | aditional_filters=pool_filter 44 | ) 45 | 46 | return super().map_data( 47 | response_data=response_data, 48 | config=config 49 | ) 50 | 51 | def get_all_pools(self): 52 | """ 53 | Returns all pools of the protocol 54 | """ 55 | 56 | config = super().get_protocol_config('pool') 57 | 58 | response_data = super().query_data_parameter( 59 | entity='pool' 60 | ) 61 | 62 | return super().map_data( 63 | response_data=response_data, 64 | config=config 65 | ) 66 | 67 | def supported_entities(self): 68 | """ 69 | Returns the supported entities for the protocol 70 | """ 71 | return super().supported_entities(self.protocol_type) 72 | -------------------------------------------------------------------------------- /deficrawler/lending.py: -------------------------------------------------------------------------------- 1 | from deficrawler.block import Block 2 | from deficrawler.protocol_base import ProtocolBase 3 | 4 | from datetime import datetime 5 | 6 | 7 | class Lending(ProtocolBase): 8 | """ 9 | Class to get data for Lending protocols 10 | """ 11 | 12 | def __init__(self, protocol, chain, version): 13 | super().__init__( 14 | protocol=protocol, 15 | chain=chain, 16 | version=version 17 | ) 18 | self.protocol_type = "lending" 19 | 20 | def get_data_from_date_range(self, from_date, to_date, entity, user=''): 21 | """ 22 | Gets data for the specified entity in the from_data to to_date period. 23 | The entities are defined in the configuration of each protocol. 24 | """ 25 | 26 | from_timestamp = int( 27 | datetime.strptime(from_date, '%d/%m/%Y %H:%M:%S').timestamp()) 28 | 29 | to_timestamp = int(datetime.strptime( 30 | to_date, '%d/%m/%Y %H:%M:%S').timestamp()) 31 | 32 | config = super().get_protocol_config(entity) 33 | 34 | aditional_filters = self.__get_aditional_filters__( 35 | user=user, entity=entity 36 | ) 37 | 38 | filter_by_block = 'block' in self.mappings_file['entities'][entity]['query']['params'] 39 | 40 | response_data = self.__get_data_from_blocks__( 41 | from_timestamp=from_timestamp, 42 | to_timestamp=to_timestamp, 43 | entity=entity, 44 | aditional_filters={} 45 | ) if filter_by_block else super().query_data_from_date_range( 46 | from_timestamp=from_timestamp, 47 | to_timestamp=to_timestamp, 48 | entity=entity, 49 | aditional_filters=aditional_filters 50 | ) 51 | 52 | return super().map_data( 53 | response_data=response_data, 54 | config=config 55 | ) 56 | 57 | def get_rates_from_date_range(self, from_date, to_date, entity, asset): 58 | """ 59 | Gets rates data for the specified entity in the from_data to to_date period. 60 | """ 61 | 62 | from_timestamp = int( 63 | datetime.strptime(from_date, '%d/%m/%Y %H:%M:%S').timestamp()) 64 | 65 | to_timestamp = int(datetime.strptime( 66 | to_date, '%d/%m/%Y %H:%M:%S').timestamp()) 67 | 68 | config = super().get_protocol_config(entity) 69 | 70 | asset_filter = { 71 | self.mappings_file['entities'][entity]['query']['params']['asset']: asset 72 | } 73 | 74 | filter_by_block = 'block' in self.mappings_file['entities'][entity]['query']['params'] 75 | 76 | response_data = self.__get_data_from_blocks__( 77 | from_timestamp=from_timestamp, 78 | to_timestamp=to_timestamp, 79 | entity=entity, 80 | aditional_filters=asset_filter 81 | ) if filter_by_block else super().query_data_from_date_range( 82 | from_timestamp=from_timestamp, 83 | to_timestamp=to_timestamp, 84 | entity=entity, 85 | aditional_filters=asset_filter 86 | ) 87 | 88 | return super().map_data( 89 | response_data=response_data, 90 | config=config 91 | ) 92 | 93 | def get_all_users(self): 94 | """ 95 | Returns all the users of the protocol 96 | """ 97 | 98 | config = super().get_protocol_config('user') 99 | 100 | response_data = super().query_data_parameter( 101 | entity='user' 102 | ) 103 | 104 | return super().map_data( 105 | response_data=response_data, 106 | config=config 107 | ) 108 | 109 | def get_all_tokens(self): 110 | """ 111 | Returns all the tokens of the protocol 112 | """ 113 | 114 | config = super().get_protocol_config('token') 115 | 116 | response_data = super().query_data_parameter( 117 | entity='token' 118 | ) 119 | 120 | return super().map_data( 121 | response_data=response_data, 122 | config=config 123 | ) 124 | 125 | def get_user_positions(self, user): 126 | """ 127 | Returns the user positions (portfolio) of the given user 128 | """ 129 | 130 | config = super().get_protocol_config('user_position') 131 | user_name = self.mappings_file['entities']['user_position']['query']['params']['user'] 132 | 133 | response_data = super().query_data_filtered( 134 | entity='user_position', 135 | filters={user_name: user} 136 | ) 137 | 138 | return super().map_data( 139 | response_data=response_data, 140 | config=config 141 | ) 142 | 143 | def supported_entities(self): 144 | """ 145 | Returns the supported entities for the protocol 146 | """ 147 | return super().supported_entities(self.protocol_type) 148 | 149 | def __get_data_from_blocks__(self, from_timestamp, to_timestamp, entity, aditional_filters): 150 | """ 151 | Returns the data in the specific range querying block by block 152 | """ 153 | blocks = Block(protocol='block', chain=self.chain, 154 | version=1) 155 | 156 | block_start = int(blocks.get_block_at_timestamp(from_timestamp)[ 157 | 0]['number']) 158 | block_end = int(blocks.get_block_at_timestamp( 159 | to_timestamp)[0]['number']) 160 | 161 | data = [] 162 | while(block_start < block_end): 163 | respose = super().query_elements_by_block(entity=entity, 164 | timestamp=from_timestamp, 165 | aditional_filters=aditional_filters, 166 | block=block_end) 167 | 168 | data = [*data, *respose] 169 | if(len(respose) == 0 or int(respose[0]['blockTimestamp']) == 0): 170 | block_end = block_start 171 | else: 172 | updated_timestamp = respose[0]['blockTimestamp'] - 1 173 | block_end = int(blocks.get_block_at_timestamp(updated_timestamp)[ 174 | 0]['number']) - 1 175 | 176 | return data 177 | 178 | def __get_aditional_filters__(self, user, entity): 179 | user_filter = {} 180 | 181 | if(user != ''): 182 | user_filter = { 183 | self.mappings_file['entities'][entity]['query']['params']['user']: user 184 | } 185 | 186 | type = {} 187 | if('type' in self.mappings_file['entities'][entity]['query']['params']): 188 | type = { 189 | 'type': self.mappings_file['entities'][entity]['query']['params']['type'] 190 | } 191 | 192 | if (len(user_filter.items()) > 0 or len(type.items()) > 0): 193 | return {**user_filter, **type} 194 | 195 | return '' 196 | -------------------------------------------------------------------------------- /deficrawler/mappers.py: -------------------------------------------------------------------------------- 1 | from deficrawler.transformer import Transformer 2 | 3 | 4 | class Mappers: 5 | """ 6 | Class to map the data from the subgraph data to the commom model defined in the json file. 7 | For each field applies the transformaton (if needed) and retuns the entity with all 8 | the fields. 9 | """ 10 | 11 | @staticmethod 12 | def map_data(response_data, protocol, chain, version, attributes, transformations, query_elements): 13 | list_elements = [] 14 | 15 | transformer = Transformer() 16 | 17 | for ele in response_data: 18 | element = {} 19 | for common_field, protocol_field in attributes.items(): 20 | element[common_field] = ( 21 | transformer.transform( 22 | element=ele, 23 | common_field=common_field, 24 | protocol_field=protocol_field, 25 | transformations=transformations, 26 | query_elements=query_elements 27 | ) 28 | ) 29 | element['protocol'] = protocol 30 | element['chain'] = chain 31 | element['version'] = version 32 | list_elements.append(element) 33 | 34 | return list_elements 35 | -------------------------------------------------------------------------------- /deficrawler/oracle.py: -------------------------------------------------------------------------------- 1 | from deficrawler.protocol_base import ProtocolBase 2 | 3 | from datetime import datetime 4 | 5 | 6 | class Oracle(ProtocolBase): 7 | """ 8 | Oracle class to get prices 9 | """ 10 | 11 | def __init__(self, protocol, chain, version): 12 | super().__init__( 13 | protocol=protocol, 14 | chain=chain, 15 | version=version 16 | ) 17 | 18 | def get_all_pairs(self): 19 | """ 20 | Returns all the existing prices for the oracle. 21 | """ 22 | 23 | config = super().get_protocol_config('pair') 24 | 25 | response_data = super().query_data_filtered( 26 | entity='pair', 27 | filters='' 28 | ) 29 | 30 | return super().map_data( 31 | response_data=response_data, 32 | config=config 33 | ) 34 | 35 | def get_price_from_date_range(self, from_date, to_date, pair): 36 | """ 37 | Returns the prices series for the specified pair in the given period 38 | """ 39 | 40 | from_timestamp = int( 41 | datetime.strptime(from_date, '%d/%m/%Y %H:%M:%S').timestamp()) 42 | 43 | to_timestamp = int(datetime.strptime( 44 | to_date, '%d/%m/%Y %H:%M:%S').timestamp()) 45 | 46 | config = super().get_protocol_config('price') 47 | 48 | pair_name = self.mappings_file['entities']['price']['query']['params']['pair'] 49 | 50 | response_data = super().query_data_from_date_range( 51 | from_timestamp=from_timestamp, 52 | to_timestamp=to_timestamp, 53 | entity='price', 54 | aditional_filters={pair_name: pair} 55 | ) 56 | 57 | return super().map_data( 58 | response_data=response_data, 59 | config=config 60 | ) 61 | 62 | def get_price_at_timestamp(self, timestamp, pair): 63 | """ 64 | Returns the prices for the specified pair in the given timestamp 65 | """ 66 | 67 | config = super().get_protocol_config('price') 68 | 69 | pair_name = self.mappings_file['entities']['price']['query']['params']['pair'] 70 | 71 | response_data = super().query_first_element( 72 | aditional_filters={pair_name: pair}, 73 | entity='price', 74 | timestamp=timestamp 75 | ) 76 | 77 | prices = super().map_data( 78 | response_data=response_data, 79 | config=config 80 | ) 81 | 82 | if len(prices) > 0: 83 | return prices[0]['price'] 84 | else: 85 | raise Exception( 86 | "Price not found for the specified pair at the timestamp") 87 | -------------------------------------------------------------------------------- /deficrawler/protocol_base.py: -------------------------------------------------------------------------------- 1 | from deficrawler.querys import Querys 2 | from deficrawler.mappers import Mappers 3 | from deficrawler.api_calls import get_data_from, get_data_parameter, get_data_filtered, get_first_element 4 | 5 | import pkgutil 6 | import json 7 | 8 | 9 | class ProtocolBase: 10 | """ 11 | Parent class to be inherit from Protocol and oracle 12 | """ 13 | 14 | def __init__(self, protocol, chain, version): 15 | self.protocol = protocol 16 | self.query_from_timestamp = Querys.QUERY_FROM_TIMESTAMP 17 | self.query_all_elements = Querys.QUERY_ALL_ELEMENTS 18 | self.query_filter = Querys.QUERY_ELEMENT_FILTER 19 | self.query_first = Querys.QUERY_FIRST_ELEMENT 20 | self.query_block = Querys.QUERY_ELEMENTS_BLOCK 21 | self.mappings_file = self.__get_protocol_file(protocol, version, chain) 22 | self.chain = chain 23 | self.version = version 24 | self.endpoint = self.__get_protocol_endpoint(chain) 25 | self.global_config = self.__load_global_config() 26 | 27 | def query_data_from_date_range(self, from_timestamp, to_timestamp, entity, aditional_filters=''): 28 | """ 29 | Gets all the data from the given entity and the specified period. One or more filters can be applied 30 | """ 31 | 32 | return get_data_from(query_input=self.query_from_timestamp, 33 | from_timestamp=from_timestamp, 34 | to_timestamp=to_timestamp, 35 | entity=entity, 36 | mappings_file=self.mappings_file, 37 | endpoint=self.endpoint, 38 | aditional_filters=aditional_filters) 39 | 40 | def query_data_parameter(self, entity): 41 | """ 42 | Gets all the existing data for the given entity 43 | """ 44 | 45 | return get_data_parameter(query_input=self.query_all_elements, 46 | entity=entity, 47 | mappings_file=self.mappings_file, 48 | endpoint=self.endpoint) 49 | 50 | def query_data_filtered(self, entity, filters): 51 | """ 52 | Gets all the existing data for the given entity with the specified filters 53 | """ 54 | 55 | return get_data_filtered(query_input=self.query_filter, 56 | entity=entity, 57 | mappings_file=self.mappings_file, 58 | endpoint=self.endpoint, 59 | filters=filters) 60 | 61 | def query_first_element(self, entity, timestamp, aditional_filters, block=None): 62 | """ 63 | Gets the first existing element for the given entity with the specified filters 64 | """ 65 | return get_first_element(query_input=self.query_first, 66 | entity=entity, 67 | mappings_file=self.mappings_file, 68 | endpoint=self.endpoint, 69 | timestamp=timestamp, 70 | aditional_filters=aditional_filters, 71 | block=block) 72 | 73 | def query_elements_by_block(self, entity, timestamp, aditional_filters, block=None): 74 | """ 75 | Gets the elements for the given entity with the specified filters and block number 76 | """ 77 | return get_first_element(query_input=self.query_block, 78 | entity=entity, 79 | mappings_file=self.mappings_file, 80 | endpoint=self.endpoint, 81 | timestamp=timestamp, 82 | aditional_filters=aditional_filters, 83 | block=block) 84 | 85 | def map_data(self, response_data, config): 86 | """ 87 | Maps the data from the subgraph data to the defined commom model in 88 | the json file 89 | """ 90 | return Mappers.map_data(response_data=response_data, 91 | protocol=self.protocol, 92 | chain=self.chain, 93 | version=self.version, 94 | attributes=config['attributes'], 95 | transformations=config['transformations'], 96 | query_elements=config['query_elements']) 97 | 98 | def get_protocol_config(self, entity): 99 | """ 100 | Gets the protocol config in the json file for the specified entity. 101 | If the entity not exists will raise an error. 102 | """ 103 | 104 | self.__exists_entity(entity) 105 | 106 | query_elements = self.mappings_file['entities'][entity]['query']['extra_fields'] 107 | query_elements.update( 108 | self.mappings_file['entities'][entity]['attributes']) 109 | 110 | return { 111 | 'attributes': self.mappings_file['entities'][entity]['attributes'], 112 | 'transformations': self.mappings_file['entities'][entity]['transformations'], 113 | 'query_elements': query_elements, 114 | } 115 | 116 | def supported_entities(self, protocol_type): 117 | """ 118 | Returns an array with the supported entities for each type of protocol 119 | """ 120 | supported = [] 121 | protocol_type_entities = self.global_config['supported_entities'][protocol_type] 122 | for attr, _ in self.mappings_file['entities'].items(): 123 | if attr in protocol_type_entities: 124 | supported.append(attr) 125 | 126 | return supported 127 | 128 | def __get_protocol_file(self, protocol, version, chain): 129 | """ 130 | Gets the json file for the specified protocol and the specified version. 131 | If the protocol does not exits at this version will raise an error. 132 | """ 133 | try: 134 | config_file = pkgutil.get_data( 135 | 'deficrawler.config', 136 | protocol.lower() + "-" + str(version) + "-" + chain.lower() + ".json" 137 | ) 138 | 139 | except FileNotFoundError: 140 | try: 141 | config_file = pkgutil.get_data( 142 | 'deficrawler.config', 143 | protocol.lower() + "-" + str(version) + ".json" 144 | ) 145 | except: 146 | raise Exception('Protocol ' + protocol + 147 | ' version ' + str(version) + ' not supported') 148 | except: 149 | raise 150 | 151 | return json.loads(config_file.decode()) 152 | 153 | def __get_protocol_endpoint(self, chain): 154 | """ 155 | Gets the endpoint for the specified chain. 156 | If the chain does not exits in the config file will raise an error. 157 | """ 158 | try: 159 | return self.mappings_file['protocol']['endpoint'][chain.lower()] 160 | except KeyError: 161 | raise Exception('Protocol ' + self.protocol + 162 | ' chain ' + chain + ' not supported') 163 | except: 164 | raise 165 | 166 | def __exists_entity(self, entity): 167 | """ 168 | Checks if the given entity exists in the entities config. 169 | In not exists will raise an error. 170 | """ 171 | if entity in self.mappings_file['entities']: 172 | return True 173 | else: 174 | raise Exception('Entity ' + entity + 175 | ' not supported for protocol ' + self.protocol) 176 | 177 | def __load_global_config(self): 178 | """ 179 | Loads the global config file 180 | """ 181 | try: 182 | global_config_file = pkgutil.get_data( 183 | "deficrawler.config", 184 | "global.json" 185 | ) 186 | 187 | except FileNotFoundError: 188 | raise Exception('Error loading global config') 189 | except: 190 | raise 191 | 192 | return json.loads(global_config_file.decode()) 193 | -------------------------------------------------------------------------------- /deficrawler/querys.py: -------------------------------------------------------------------------------- 1 | class Querys: 2 | QUERY_FROM_TIMESTAMP = """{{ 3 | {entity_name}( 4 | first: 1000 5 | orderBy: {order_by} 6 | orderDirection: asc 7 | where: {{ 8 | {order_by}_gt: {from_timestamp} 9 | {order_by}_lte: {to_timestamp} 10 | {aditional_filters} 11 | }} 12 | ){{ 13 | {attributes} 14 | }} 15 | }} 16 | """ 17 | 18 | QUERY_ALL_ELEMENTS = """ {{ 19 | {entity_name}( 20 | first: 1000 21 | orderBy: {order_by} 22 | orderDirection: asc 23 | where: {{ 24 | {order_by}_gt:"{filter_value}" 25 | }} 26 | ){{ 27 | {attributes} 28 | }} 29 | }} 30 | """ 31 | 32 | QUERY_ELEMENT_FILTER = """ {{ 33 | {entity_name}( 34 | first: 1000 35 | where: {{ 36 | {filters} 37 | }} 38 | ){{ 39 | {attributes} 40 | }} 41 | }} 42 | """ 43 | 44 | QUERY_FIRST_ELEMENT = """ {{ 45 | {entity_name}( 46 | orderBy: {order_by} 47 | orderDirection: desc 48 | first: 1 49 | {block} 50 | where: {{ 51 | {order_by_filter}{lte} {timestamp} 52 | {aditional_filters} 53 | }} 54 | ){{ 55 | {attributes} 56 | }} 57 | }} 58 | """ 59 | 60 | QUERY_ELEMENTS_BLOCK = """ {{ 61 | {entity_name}( 62 | orderBy: {order_by} 63 | orderDirection: desc 64 | first: 1000 65 | {block} 66 | where: {{ 67 | {order_by_filter}{lte} {timestamp} 68 | {aditional_filters} 69 | }} 70 | ){{ 71 | {attributes} 72 | }} 73 | }} 74 | """ 75 | -------------------------------------------------------------------------------- /deficrawler/utils.py: -------------------------------------------------------------------------------- 1 | from datetime import time 2 | 3 | 4 | def get_attributes(entity, map_file): 5 | """ 6 | Returns the list of attributes for the given map file and entity. 7 | The list is created joining the attributes of the entity and the 8 | extra fields (if exists) to create the query 9 | """ 10 | list_attr = '' 11 | attributes = map_file['entities'][entity]['query']['extra_fields'] 12 | attributes.update(map_file['entities'][entity]['attributes']) 13 | for attribute, value in attributes.items(): 14 | list_attr += format_attribute(value) + " " 15 | return list_attr 16 | 17 | 18 | def get_filters(filter_dict): 19 | """ 20 | Returns the filters list in string mode for a given dictionary. 21 | Gets all the filters that the dictionary contains and create a list 22 | of key:value elements 23 | """ 24 | filters = '' 25 | 26 | if type(filter_dict) is dict: 27 | for filter_name, filter_value in filter_dict.items(): 28 | filters += filter_name + ":\"" + filter_value + "\"\n" 29 | 30 | return filters 31 | 32 | 33 | def format_element(list_elements): 34 | """ 35 | Formats the element to query the subgraph. 36 | If only one element is given returns the element, in other case 37 | format the element with the format element{subelement{subsubelement}} 38 | """ 39 | if(len(list_elements) == 1): 40 | return list_elements[0] 41 | 42 | path = list_elements[0] + '{' 43 | for index, field in enumerate(list_elements): 44 | if index > 0 and index % 2 != 0: 45 | path += field 46 | if index > 0 and index % 2 == 0: 47 | path += '{'+field+'}' 48 | 49 | path += '}' 50 | return path 51 | 52 | 53 | def format_attribute(list_fields): 54 | """ 55 | Format the attribute to base on the information of the json file. 56 | For each field calls the format element, can be a single list wich 57 | returns a single element or a list of lists that will concatenate the 58 | strings for each list 59 | """ 60 | str_list_attr = "" 61 | 62 | if(isinstance(list_fields[0], list)): 63 | for list_elements in list_fields: 64 | str_list_attr += format_element(list_elements) + " " 65 | else: 66 | str_list_attr += format_element(list_fields) 67 | return str_list_attr 68 | 69 | 70 | def filter_method(block, order_by_filter, lte, timestamp): 71 | """ 72 | Returns the block filter or the where filter depending of the block passed 73 | """ 74 | block_ret = '' 75 | order_by_filter_ret = '' 76 | lte_ret = '' 77 | timestamp_ret = '' 78 | 79 | if block: 80 | block_ret = "block:{{ number: {number} }}".format(number=block) 81 | else: 82 | order_by_filter_ret = order_by_filter 83 | lte_ret = lte 84 | timestamp_ret = timestamp 85 | 86 | return { 87 | 'block': block_ret, 88 | 'order_by_filter': order_by_filter_ret, 89 | 'lte': lte_ret, 90 | 'timestamp': timestamp_ret 91 | } 92 | -------------------------------------------------------------------------------- /docs/entities/Amm.md: -------------------------------------------------------------------------------- 1 | # Automated markets makers 2 | 3 | This document describes the different entities that can be retrieved from the amms protocols 4 | 5 | ## Swap 6 | 7 | Field | Description | Type 8 | --------|-------|-------------- 9 | Transaction id | Transaction id of the swap | String 10 | User | User that executed the swap | String 11 | From Token | Token symbol of swap origin | String 12 | To Token | Token symbol of swap destination | String 13 | From Token Amount | Token amount of swap origin | Decimal 14 | To Token Amount | Token amount of swap destination | String 15 | Timestamp | Timestamp of deposit | Timestamp 16 | 17 | ## Pool 18 | 19 | Field | Description | Type 20 | --------|-------|-------------- 21 | Id | Unique identifier for pool | String 22 | Pool tokens | List of tokens of the pool | String -------------------------------------------------------------------------------- /docs/entities/Lending.md: -------------------------------------------------------------------------------- 1 | # Lending protocols 2 | 3 | This document describes the different entities that can be retrieved from the lending protocols 4 | 5 | ## Deposits 6 | 7 | Field | Description | Type 8 | --------|-------|-------------- 9 | User | User | String 10 | Amount | Amount of token deposited | Decimal 11 | Token | Token symbol of deposit | String 12 | Timestamp | Timestamp of deposit | Timestamp 13 | 14 | ## Borrows 15 | 16 | Field | Description | Type 17 | --------|-------|-------------- 18 | User | User | String 19 | Amount | Amount of token deposited | Decimal 20 | Token | Token symbol of borrow | String 21 | Timestamp | Timestamp of borrow | Timestamp 22 | 23 | ## Repay 24 | 25 | Field | Description | Type 26 | --------|-------|-------------- 27 | User | User | String 28 | Amount | Amount of token repaid | Decimal 29 | Token | Token symbol of repaid | String 30 | Timestamp | Timestamp of repaid | Timestamp 31 | 32 | ## Liquidation 33 | 34 | Field | Description | Type 35 | --------|-------|-------------- 36 | User | User | String 37 | Principal Token | Token payed on liquidation to repay debt | Decimal 38 | Collateral Token | Token received by liquidator on liquidation | String 39 | Principal Amount | Amount of principal payed on liquidation | Timestamp 40 | Collateral Amount | Amount of collateral recevided by liquidator | Decimal 41 | Liquidator | Address of the liquidator | String 42 | Timestamp | Timestamp of liquidation | Timestamp 43 | 44 | ## User 45 | 46 | Field | Description | Type 47 | --------|-------|-------------- 48 | User id | User | String 49 | Active loans | Number of loans that the user has currently open | Integer 50 | Liquidations Count | Number of liquidations received by the user | Integer 51 | 52 | ## User positions 53 | 54 | Field | Description | Type 55 | --------|-------|-------------- 56 | User | User | String 57 | Symbol | Symbol of the token in the user portfolio | String 58 | Debt amount | Amount of debt tokens | Decimal 59 | Collateral amount | Amount of collateral tokens | Decimal -------------------------------------------------------------------------------- /docs/entities/Prices.md: -------------------------------------------------------------------------------- 1 | # Prices entities 2 | 3 | This document describes the different entities that can be retrieved from prices 4 | 5 | ## Prices pairs 6 | 7 | Field | Description | Type 8 | --------|-------|-------------- 9 | id | Unique identifier of price feed | String 10 | 11 | ## Price 12 | 13 | Field | Description | Type 14 | --------|-------|-------------- 15 | Asset Pair | Pair of tokens for the price feed | Decimal 16 | Price | Exchange price of the asset pair | Decimal 17 | Timestamp | Timestamp of price update | Timestamp 18 | 19 | -------------------------------------------------------------------------------- /docs/examples.py: -------------------------------------------------------------------------------- 1 | from deficrawler import Oracle 2 | from deficrawler import Dex 3 | from deficrawler import Lending 4 | 5 | # Lending protocols 6 | aave = Lending(protocol="Aave", chain="Ethereum", version=2) 7 | aave_polygon = Lending(protocol="Aave", chain="Polygon", version=2) 8 | compound = Lending(protocol="Compound", chain="Ethereum", version=2) 9 | cream = Lending(protocol="Cream", chain="Ethereum", version=2) 10 | cream_bsc = Lending(protocol="Cream", chain="bsc", version=2) 11 | 12 | 13 | # Supported entities for aave 14 | print(aave.supported_entities()) 15 | 16 | # Get borrows in a time period 17 | start_date = '21/04/2021 00:00:01' 18 | end_date = '24/04/2021 23:59:00' 19 | 20 | 21 | list_borrows = [*aave.get_data_from_date_range(start_date, end_date, "borrow"), 22 | *aave_polygon.get_data_from_date_range(start_date, end_date, "borrow"), 23 | *compound.get_data_from_date_range(start_date, end_date, "borrow"), 24 | *cream_bsc.get_data_from_date_range(start_date, end_date, "borrow"), 25 | *cream.get_data_from_date_range(start_date, end_date, "borrow")] 26 | 27 | 28 | print(list_borrows) 29 | 30 | 31 | # AMM protocols 32 | uniswap = Dex(protocol="Uniswap", chain="Ethereum", version=2) 33 | balancer = Dex(protocol="Balancer", chain="Ethereum", version=1) 34 | bancor = Dex("Bancor", chain="Ethereum", version=1) 35 | shushi = Dex("SushiSwap", chain="Ethereum", version=1) 36 | 37 | 38 | # Get all the swaps in a time range 39 | start_date_amm = '10/05/2021 00:00:00' 40 | end_date_amm = '10/05/2021 02:00:00' 41 | 42 | list_swaps = [*uniswap.get_data_from_date_range(start_date_amm, end_date_amm, "swap"), 43 | *balancer.get_data_from_date_range(start_date_amm, end_date_amm, "swap"), 44 | *bancor.get_data_from_date_range(start_date_amm, end_date_amm, "swap"), 45 | *shushi.get_data_from_date_range(start_date_amm, end_date_amm, "swap")] 46 | 47 | 48 | print(list_swaps) 49 | 50 | # Oracles 51 | chainlink = Oracle(protocol="chainlink", version=1, chain="Ethereum") 52 | 53 | # Get the ETH/USD price of a period 54 | start_date = '10/04/2021 00:00:01' 55 | end_date = '10/05/2021 23:59:00' 56 | price_eth = chainlink.get_price_from_date_range( 57 | from_date=start_date, to_date=end_date, pair="ETH/USD") 58 | 59 | print(price_eth) 60 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from codecs import open 2 | import os 3 | from setuptools import setup, find_packages 4 | 5 | here = os.path.abspath(os.path.dirname(__file__)) 6 | 7 | with open(os.path.join(here, 'README.md'), encoding='utf-8') as f: 8 | long_description = f.read() 9 | 10 | setup( 11 | name='deficrawler', 12 | description='Python package to query DeFi data from several The Graph subgraphs', 13 | classifiers=[ 14 | 'Development Status :: 5 - Production/Stable', 15 | 'Intended Audience :: Developers', 16 | 'License :: OSI Approved :: Apache Software License', 17 | 'Natural Language :: English', 18 | 'Programming Language :: Python :: 3.7', 19 | ], 20 | long_description=long_description, 21 | long_description_content_type='text/markdown', 22 | include_package_data=True, 23 | version='0.4.0', 24 | author='keyko.io', 25 | author_email='root@keyko.io', 26 | url='https://github.com/keyko-io/defi-crawler-py', 27 | license='MIT', 28 | install_requires=[ 29 | 'dict_digger', 30 | 'requests', 31 | 'retry' 32 | ], 33 | setup_requires=['pytest-runner'], 34 | tests_require=['pytest'], 35 | keywords=[ 36 | 'finance', 37 | 'analysis', 38 | ], 39 | packages=find_packages(exclude=['contrib', 'docs', 'tests*']), 40 | python_requires='>=3' 41 | ) 42 | -------------------------------------------------------------------------------- /tests/int/test_blocks.py: -------------------------------------------------------------------------------- 1 | from deficrawler.block import Block 2 | 3 | 4 | def test_block_bsc(): 5 | block = Block(protocol='block', chain='bsc', version='1') 6 | block_info = block.get_block_at_timestamp(timestamp=1623673813) 7 | assert(int(block_info[0]['number']) == 8289859) 8 | 9 | block_info = block.get_block_info(block_number=8289859) 10 | assert(int(block_info[0]['timestamp']) == 1623673811) 11 | 12 | 13 | 14 | def test_block_ethereum(): 15 | block = Block(protocol='block', chain='Ethereum', version='1') 16 | block_info = block.get_block_at_timestamp(timestamp=1623673813) 17 | assert(int(block_info[0]['number']) == 12632560) 18 | 19 | block_info = block.get_block_info(block_number=12632560) 20 | assert(int(block_info[0]['timestamp']) == 1623673813) 21 | 22 | 23 | def test_block_polygon(): 24 | block = Block(protocol='block', chain='Polygon', version='1') 25 | block_info = block.get_block_at_timestamp(timestamp=1617176896) 26 | print(block_info[0]['number']) 27 | assert(int(block_info[0]['number']) == 12685220) 28 | 29 | block_info = block.get_block_info(block_number=12685220) 30 | assert(int(block_info[0]['timestamp']) == 1617176896) 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /tests/int/test_burn.py: -------------------------------------------------------------------------------- 1 | from deficrawler.dex import Dex 2 | 3 | 4 | def test_burn_uniswap_2_eth(): 5 | uniswap = Dex(protocol="Uniswap", chain="Ethereum", version=2) 6 | burns = uniswap.get_data_from_date_range( 7 | '04/05/2021 00:00:00', '04/05/2021 00:10:30', "burn") 8 | 9 | assert(burns[0]['tx_id'] != "") 10 | assert(burns[0]['protocol'] == "Uniswap") 11 | assert(burns[0]['chain'] == "Ethereum") 12 | assert(burns[0]['version'] == 2) 13 | assert(burns[0]['user'] != "") 14 | assert(burns[0]['token0'] != "") 15 | assert(burns[0]['token1'] != "") 16 | assert(burns[0]['pool'] != "") 17 | assert(float(burns[0]['amount0']) > 0) 18 | assert(float(burns[0]['amount1']) > 0) 19 | assert(float(burns[0]['timestamp']) > 0) 20 | 21 | 22 | def test_burn_uniswap_3_eth(): 23 | uniswap = Dex(protocol="Uniswap", chain="Ethereum", version=3) 24 | burns = uniswap.get_data_from_date_range( 25 | '30/09/2021 00:00:00', '30/09/2021 02:00:30', "burn") 26 | 27 | assert(burns[0]['tx_id'] != "") 28 | assert(burns[0]['protocol'] == "Uniswap") 29 | assert(burns[0]['chain'] == "Ethereum") 30 | assert(burns[0]['version'] == 3) 31 | assert(burns[0]['user'] != "") 32 | assert(burns[0]['token0'] != "") 33 | assert(burns[0]['token1'] != "") 34 | assert(burns[0]['pool'] != "") 35 | assert(float(burns[0]['amount0']) > 0) 36 | assert(float(burns[0]['amount1']) >= 0) 37 | assert(float(burns[0]['timestamp']) > 0) 38 | 39 | 40 | 41 | # def test_burn_ubeswap_2_celo(): 42 | # ubeswap = Dex(protocol="Ubeswap", chain="Celo", version=1) 43 | # burns = ubeswap.get_data_from_date_range( 44 | # '30/09/2021 00:00:00', '30/09/2021 01:00:30', "burn") 45 | 46 | # assert(burns[0]['tx_id'] != "") 47 | # assert(burns[0]['protocol'] == "Ubeswap") 48 | # assert(burns[0]['chain'] == "Celo") 49 | # assert(burns[0]['version'] == 1) 50 | # assert(burns[0]['user'] != "") 51 | # assert(burns[0]['token0'] != "") 52 | # assert(burns[0]['token1'] != "") 53 | # assert(burns[0]['pool'] != "") 54 | # assert(float(burns[0]['amount0']) > 0) 55 | # assert(float(burns[0]['amount1']) > 0) 56 | # assert(float(burns[0]['timestamp']) > 0) 57 | 58 | 59 | def test_burn_sushi_2_eth(): 60 | sushi = Dex(protocol="Sushiswap", chain="Ethereum", version=1) 61 | burns = sushi.get_data_from_date_range( 62 | '30/09/2021 00:00:00', '30/09/2021 01:00:30', "burn") 63 | 64 | assert(burns[0]['tx_id'] != "") 65 | assert(burns[0]['protocol'] == "Sushiswap") 66 | assert(burns[0]['chain'] == "Ethereum") 67 | assert(burns[0]['version'] == 1) 68 | assert(burns[0]['user'] != "") 69 | assert(burns[0]['token0'] != "") 70 | assert(burns[0]['token1'] != "") 71 | assert(burns[0]['pool'] != "") 72 | assert(float(burns[0]['amount0']) > 0) 73 | assert(float(burns[0]['amount1']) > 0) 74 | assert(float(burns[0]['timestamp']) > 0) 75 | 76 | def test_burn_sushi_2_bsc(): 77 | sushi = Dex(protocol="Sushiswap", chain="bsc", version=1) 78 | burns = sushi.get_data_from_date_range( 79 | '30/09/2021 00:00:00', '30/09/2021 02:00:30', "burn") 80 | 81 | assert(burns[0]['tx_id'] != "") 82 | assert(burns[0]['protocol'] == "Sushiswap") 83 | assert(burns[0]['chain'] == "bsc") 84 | assert(burns[0]['version'] == 1) 85 | assert(burns[0]['user'] != "") 86 | assert(burns[0]['token0'] != "") 87 | assert(burns[0]['token1'] != "") 88 | assert(burns[0]['pool'] != "") 89 | assert(float(burns[0]['amount0']) > 0) 90 | assert(float(burns[0]['amount1']) > 0) 91 | assert(float(burns[0]['timestamp']) > 0) 92 | 93 | 94 | def test_burn_sushi_2_polygon(): 95 | sushi = Dex(protocol="Sushiswap", chain="polygon", version=1) 96 | burns = sushi.get_data_from_date_range( 97 | '30/09/2021 00:00:00', '30/09/2021 01:00:30', "burn") 98 | 99 | assert(burns[0]['tx_id'] != "") 100 | assert(burns[0]['protocol'] == "Sushiswap") 101 | assert(burns[0]['chain'] == "polygon") 102 | assert(burns[0]['version'] == 1) 103 | assert(burns[0]['user'] != "") 104 | assert(burns[0]['token0'] != "") 105 | assert(burns[0]['token1'] != "") 106 | assert(burns[0]['pool'] != "") 107 | assert(float(burns[0]['amount0']) > 0) 108 | assert(float(burns[0]['amount1']) > 0) 109 | assert(float(burns[0]['timestamp']) > 0) 110 | 111 | def test_burn_sushi_2_fantom(): 112 | sushi = Dex(protocol="Sushiswap", chain="fantom", version=1) 113 | burns = sushi.get_data_from_date_range( 114 | '30/09/2021 00:00:00', '30/09/2021 09:00:30', "burn") 115 | 116 | assert(burns[0]['tx_id'] != "") 117 | assert(burns[0]['protocol'] == "Sushiswap") 118 | assert(burns[0]['chain'] == "fantom") 119 | assert(burns[0]['version'] == 1) 120 | assert(burns[0]['user'] != "") 121 | assert(burns[0]['token0'] != "") 122 | assert(burns[0]['token1'] != "") 123 | assert(burns[0]['pool'] != "") 124 | assert(float(burns[0]['amount0']) > 0) 125 | assert(float(burns[0]['amount1']) > 0) 126 | assert(float(burns[0]['timestamp']) > 0) 127 | 128 | 129 | def test_burn_sushi_1_celo(): 130 | sushi = Dex(protocol="Sushiswap", chain="celo", version=1) 131 | burns = sushi.get_data_from_date_range( 132 | '17/10/2021 00:00:00', '17/10/2021 03:00:30', "burn") 133 | 134 | assert(burns[0]['tx_id'] != "") 135 | assert(burns[0]['protocol'] == "Sushiswap") 136 | assert(burns[0]['chain'] == "celo") 137 | assert(burns[0]['version'] == 1) 138 | assert(burns[0]['user'] != "") 139 | assert(burns[0]['token0'] != "") 140 | assert(burns[0]['token1'] != "") 141 | assert(burns[0]['pool'] != "") 142 | assert(float(burns[0]['amount0']) > 0) 143 | assert(float(burns[0]['amount1']) > 0) 144 | assert(float(burns[0]['timestamp']) > 0) 145 | 146 | 147 | def test_burn_quickswap_1_polygon(): 148 | quickswap = Dex(protocol="quickswap", chain="polygon", version=1) 149 | burns = quickswap.get_data_from_date_range( 150 | '30/09/2021 00:00:00', '30/09/2021 01:00:30', "burn") 151 | 152 | assert(burns[0]['tx_id'] != "") 153 | assert(burns[0]['protocol'] == "quickswap") 154 | assert(burns[0]['chain'] == "polygon") 155 | assert(burns[0]['version'] == 1) 156 | assert(burns[0]['user'] != "") 157 | assert(burns[0]['token0'] != "") 158 | assert(burns[0]['token1'] != "") 159 | assert(burns[0]['pool'] != "") 160 | assert(float(burns[0]['amount0']) > 0) 161 | assert(float(burns[0]['amount1']) > 0) 162 | assert(float(burns[0]['timestamp']) > 0) 163 | 164 | 165 | 166 | def test_burn_pangolin_1_avalanche(): 167 | pangolin = Dex(protocol="pangolin", chain="avalanche", version=1) 168 | mints = pangolin.get_data_from_date_range( 169 | '30/09/2021 00:00:00', '30/09/2021 01:00:30', "burn") 170 | 171 | assert(mints[0]['tx_id'] != "") 172 | assert(mints[0]['protocol'] == "pangolin") 173 | assert(mints[0]['chain'] == "avalanche") 174 | assert(mints[0]['version'] == 1) 175 | assert(mints[0]['user'] != "") 176 | assert(mints[0]['token0'] != "") 177 | assert(mints[0]['token1'] != "") 178 | assert(mints[0]['pool'] != "") 179 | assert(float(mints[0]['amount0']) > 0) 180 | assert(float(mints[0]['amount1']) > 0) 181 | assert(float(mints[0]['timestamp']) > 0) 182 | -------------------------------------------------------------------------------- /tests/int/test_flashloans.py: -------------------------------------------------------------------------------- 1 | from deficrawler.lending import Lending 2 | 3 | 4 | def test_flashloans_aave_2_eth(): 5 | aave = Lending(protocol="Aave", chain="Ethereum", version=2) 6 | flash_loans = aave.get_data_from_date_range( 7 | '30/08/2021 00:00:01', '30/08/2021 18:01:00', "flashloans") 8 | 9 | assert(flash_loans[0]['tx_id'] != "") 10 | assert(flash_loans[0]['protocol'] == "Aave") 11 | assert(flash_loans[0]['chain'] == "Ethereum") 12 | assert(flash_loans[0]['version'] == 2) 13 | assert(flash_loans[0]['user'] != "") 14 | assert(flash_loans[0]['token'] != "") 15 | assert(flash_loans[0]['amount'] > 0) 16 | assert(flash_loans[0]['timestamp'] > 0) 17 | 18 | 19 | def test_flashloans_aave_2_avalanche(): 20 | aave = Lending(protocol="Aave", chain="Avalanche", version=2) 21 | flash_loans = aave.get_data_from_date_range( 22 | '10/10/2021 00:00:01', '18/10/2021 18:01:00', "flashloans") 23 | 24 | assert(flash_loans[0]['tx_id'] != "") 25 | assert(flash_loans[0]['protocol'] == "Aave") 26 | assert(flash_loans[0]['chain'] == "Avalanche") 27 | assert(flash_loans[0]['version'] == 2) 28 | assert(flash_loans[0]['user'] != "") 29 | assert(flash_loans[0]['token'] != "") 30 | assert(flash_loans[0]['amount'] > 0) 31 | assert(flash_loans[0]['timestamp'] > 0) 32 | 33 | 34 | def test_flashloans_aave_2_eth_user(): 35 | aave = Lending(protocol="Aave", chain="Ethereum", version=2) 36 | flash_loans = aave.get_data_from_date_range( 37 | '30/08/2021 00:00:01', '30/08/2021 18:01:00', "flashloans", "0x4f2769e87c7d96ed9ca72084845ee05e7de5dda2") 38 | 39 | for flash_loan in flash_loans: 40 | assert(flash_loan['user'] == 41 | "0x4f2769e87c7d96ed9ca72084845ee05e7de5dda2") 42 | 43 | 44 | def test_flashloans_aave_2_polygon(): 45 | aave = Lending(protocol="Aave", chain="Polygon", version=2) 46 | flash_loans = aave.get_data_from_date_range( 47 | '30/08/2021 00:00:01', '30/08/2021 18:01:00', "flashloans") 48 | assert(flash_loans[0]['tx_id'] != "") 49 | assert(flash_loans[0]['protocol'] == "Aave") 50 | assert(flash_loans[0]['chain'] == "Polygon") 51 | assert(flash_loans[0]['version'] == 2) 52 | assert(flash_loans[0]['user'] != "") 53 | assert(flash_loans[0]['token'] != "") 54 | assert(flash_loans[0]['amount'] > 0) 55 | assert(flash_loans[0]['timestamp'] > 0) 56 | 57 | 58 | def test_flashloans_aave_2_polygon_user(): 59 | aave = Lending(protocol="Aave", chain="Polygon", version=2) 60 | flash_loans = aave.get_data_from_date_range( 61 | '30/08/2021 00:00:01', '30/08/2021 18:01:00', "flashloans", "0xabcd3c5e8aed3b8d8096f0f33c7aa1cb5d555dfb") 62 | 63 | for flash_loan in flash_loans: 64 | assert(flash_loan['user'] == 65 | "0xabcd3c5e8aed3b8d8096f0f33c7aa1cb5d555dfb") 66 | 67 | 68 | def test_flashloans_aave_3_polygon(): 69 | aave = Lending(protocol="Aave", chain="Polygon", version=3) 70 | flash_loans = aave.get_data_from_date_range( 71 | '01/05/2022 00:00:01', '02/05/2022 18:01:00', "flashloans") 72 | assert(flash_loans[0]['tx_id'] != "") 73 | assert(flash_loans[0]['protocol'] == "Aave") 74 | assert(flash_loans[0]['chain'] == "Polygon") 75 | assert(flash_loans[0]['version'] == 3) 76 | assert(flash_loans[0]['user'] != "") 77 | assert(flash_loans[0]['token'] != "") 78 | assert(flash_loans[0]['amount'] > 0) 79 | assert(flash_loans[0]['timestamp'] > 0) 80 | 81 | def test_flashloans_aave_3_arbitrum(): 82 | aave = Lending(protocol="Aave", chain="Arbitrum", version=3) 83 | flash_loans = aave.get_data_from_date_range( 84 | '01/05/2022 00:00:01', '02/05/2022 18:01:00', "flashloans") 85 | assert(flash_loans[0]['tx_id'] != "") 86 | assert(flash_loans[0]['protocol'] == "Aave") 87 | assert(flash_loans[0]['chain'] == "Arbitrum") 88 | assert(flash_loans[0]['version'] == 3) 89 | assert(flash_loans[0]['user'] != "") 90 | assert(flash_loans[0]['token'] != "") 91 | assert(flash_loans[0]['amount'] > 0) 92 | assert(flash_loans[0]['timestamp'] > 0) 93 | 94 | 95 | def test_flashloans_aave_3_optimism(): 96 | aave = Lending(protocol="Aave", chain="Optimism", version=3) 97 | flash_loans = aave.get_data_from_date_range( 98 | '01/05/2022 00:00:01', '02/05/2022 18:01:00', "flashloans") 99 | assert(flash_loans[0]['tx_id'] != "") 100 | assert(flash_loans[0]['protocol'] == "Aave") 101 | assert(flash_loans[0]['chain'] == "Optimism") 102 | assert(flash_loans[0]['version'] == 3) 103 | assert(flash_loans[0]['user'] != "") 104 | assert(flash_loans[0]['token'] != "") 105 | assert(flash_loans[0]['amount'] > 0) 106 | assert(flash_loans[0]['timestamp'] > 0) 107 | 108 | 109 | def test_flashloans_aave_3_fantom(): 110 | aave = Lending(protocol="Aave", chain="Fantom", version=3) 111 | flash_loans = aave.get_data_from_date_range( 112 | '01/05/2022 00:00:01', '02/05/2022 18:01:00', "flashloans") 113 | assert(flash_loans[0]['tx_id'] != "") 114 | assert(flash_loans[0]['protocol'] == "Aave") 115 | assert(flash_loans[0]['chain'] == "Fantom") 116 | assert(flash_loans[0]['version'] == 3) 117 | assert(flash_loans[0]['user'] != "") 118 | assert(flash_loans[0]['token'] != "") 119 | assert(flash_loans[0]['amount'] > 0) 120 | assert(flash_loans[0]['timestamp'] > 0) 121 | 122 | 123 | def test_flashloans_aave_3_avalanche(): 124 | aave = Lending(protocol="Aave", chain="Avalanche", version=3) 125 | flash_loans = aave.get_data_from_date_range( 126 | '01/05/2022 00:00:01', '02/05/2022 18:01:00', "flashloans") 127 | assert(flash_loans[0]['tx_id'] != "") 128 | assert(flash_loans[0]['protocol'] == "Aave") 129 | assert(flash_loans[0]['chain'] == "Avalanche") 130 | assert(flash_loans[0]['version'] == 3) 131 | assert(flash_loans[0]['user'] != "") 132 | assert(flash_loans[0]['token'] != "") 133 | assert(flash_loans[0]['amount'] > 0) 134 | assert(flash_loans[0]['timestamp'] > 0) -------------------------------------------------------------------------------- /tests/int/test_mint.py: -------------------------------------------------------------------------------- 1 | from deficrawler.dex import Dex 2 | 3 | 4 | def test_mint_uniswap_2_eth(): 5 | uniswap = Dex(protocol="Uniswap", chain="Ethereum", version=2) 6 | mints = uniswap.get_data_from_date_range( 7 | '04/05/2021 00:00:00', '04/05/2021 00:30:30', "mint") 8 | 9 | assert(mints[0]['tx_id'] != "") 10 | assert(mints[0]['protocol'] == "Uniswap") 11 | assert(mints[0]['chain'] == "Ethereum") 12 | assert(mints[0]['version'] == 2) 13 | assert(mints[0]['user'] != "") 14 | assert(mints[0]['token0'] != "") 15 | assert(mints[0]['token1'] != "") 16 | assert(mints[0]['pool'] != "") 17 | assert(float(mints[0]['amount0']) > 0) 18 | assert(float(mints[0]['amount1']) > 0) 19 | assert(float(mints[0]['timestamp']) > 0) 20 | 21 | 22 | def test_mint_uniswap_3_eth(): 23 | uniswap = Dex(protocol="Uniswap", chain="Ethereum", version=3) 24 | mints = uniswap.get_data_from_date_range( 25 | '30/09/2021 00:00:00', '30/09/2021 02:00:30', "mint") 26 | 27 | assert(mints[0]['tx_id'] != "") 28 | assert(mints[0]['protocol'] == "Uniswap") 29 | assert(mints[0]['chain'] == "Ethereum") 30 | assert(mints[0]['version'] == 3) 31 | assert(mints[0]['user'] != "") 32 | assert(mints[0]['token0'] != "") 33 | assert(mints[0]['token1'] != "") 34 | assert(mints[0]['pool'] != "") 35 | assert(float(mints[0]['amount0']) > 0) 36 | assert(float(mints[0]['amount1']) > 0) 37 | assert(float(mints[0]['timestamp']) > 0) 38 | 39 | 40 | 41 | # def test_mint_ubeswap_2_celo(): 42 | # ubeswap = Dex(protocol="Ubeswap", chain="Celo", version=1) 43 | # mints = ubeswap.get_data_from_date_range( 44 | # '30/09/2021 00:00:00', '30/09/2021 01:00:30', "mint") 45 | 46 | # assert(mints[0]['tx_id'] != "") 47 | # assert(mints[0]['protocol'] == "Ubeswap") 48 | # assert(mints[0]['chain'] == "Celo") 49 | # assert(mints[0]['version'] == 1) 50 | # assert(mints[0]['user'] != "") 51 | # assert(mints[0]['token0'] != "") 52 | # assert(mints[0]['token1'] != "") 53 | # assert(mints[0]['pool'] != "") 54 | # assert(float(mints[0]['amount0']) > 0) 55 | # assert(float(mints[0]['amount1']) > 0) 56 | # assert(float(mints[0]['timestamp']) > 0) 57 | 58 | 59 | def test_mint_sushi_2_eth(): 60 | sushi = Dex(protocol="Sushiswap", chain="Ethereum", version=1) 61 | mints = sushi.get_data_from_date_range( 62 | '30/09/2021 00:00:00', '30/09/2021 01:00:30', "mint") 63 | 64 | assert(mints[0]['tx_id'] != "") 65 | assert(mints[0]['protocol'] == "Sushiswap") 66 | assert(mints[0]['chain'] == "Ethereum") 67 | assert(mints[0]['version'] == 1) 68 | assert(mints[0]['user'] != "") 69 | assert(mints[0]['token0'] != "") 70 | assert(mints[0]['token1'] != "") 71 | assert(mints[0]['pool'] != "") 72 | assert(float(mints[0]['amount0']) > 0) 73 | assert(float(mints[0]['amount1']) > 0) 74 | assert(float(mints[0]['timestamp']) > 0) 75 | 76 | def test_mint_sushi_2_bsc(): 77 | sushi = Dex(protocol="Sushiswap", chain="bsc", version=1) 78 | mints = sushi.get_data_from_date_range( 79 | '30/09/2021 00:00:00', '30/09/2021 02:00:30', "mint") 80 | 81 | assert(mints[0]['tx_id'] != "") 82 | assert(mints[0]['protocol'] == "Sushiswap") 83 | assert(mints[0]['chain'] == "bsc") 84 | assert(mints[0]['version'] == 1) 85 | assert(mints[0]['user'] != "") 86 | assert(mints[0]['token0'] != "") 87 | assert(mints[0]['token1'] != "") 88 | assert(mints[0]['pool'] != "") 89 | assert(float(mints[0]['amount0']) > 0) 90 | assert(float(mints[0]['amount1']) > 0) 91 | assert(float(mints[0]['timestamp']) > 0) 92 | 93 | 94 | def test_mint_sushi_2_polygon(): 95 | sushi = Dex(protocol="Sushiswap", chain="polygon", version=1) 96 | mints = sushi.get_data_from_date_range( 97 | '30/09/2021 00:00:00', '30/09/2021 01:00:30', "mint") 98 | 99 | assert(mints[0]['tx_id'] != "") 100 | assert(mints[0]['protocol'] == "Sushiswap") 101 | assert(mints[0]['chain'] == "polygon") 102 | assert(mints[0]['version'] == 1) 103 | assert(mints[0]['user'] != "") 104 | assert(mints[0]['token0'] != "") 105 | assert(mints[0]['token1'] != "") 106 | assert(mints[0]['pool'] != "") 107 | assert(float(mints[0]['amount0']) > 0) 108 | assert(float(mints[0]['amount1']) > 0) 109 | assert(float(mints[0]['timestamp']) > 0) 110 | 111 | def test_mint_sushi_2_fantom(): 112 | sushi = Dex(protocol="Sushiswap", chain="fantom", version=1) 113 | mints = sushi.get_data_from_date_range( 114 | '30/09/2021 00:00:00', '30/09/2021 01:00:30', "mint") 115 | 116 | assert(mints[0]['tx_id'] != "") 117 | assert(mints[0]['protocol'] == "Sushiswap") 118 | assert(mints[0]['chain'] == "fantom") 119 | assert(mints[0]['version'] == 1) 120 | assert(mints[0]['user'] != "") 121 | assert(mints[0]['token0'] != "") 122 | assert(mints[0]['token1'] != "") 123 | assert(mints[0]['pool'] != "") 124 | assert(float(mints[0]['amount0']) > 0) 125 | assert(float(mints[0]['amount1']) > 0) 126 | assert(float(mints[0]['timestamp']) > 0) 127 | 128 | def test_mint_sushi_1_celo(): 129 | sushi = Dex(protocol="Sushiswap", chain="celo", version=1) 130 | mints = sushi.get_data_from_date_range( 131 | '17/10/2021 00:00:00', '17/10/2021 03:00:30', "mint") 132 | 133 | assert(mints[0]['tx_id'] != "") 134 | assert(mints[0]['protocol'] == "Sushiswap") 135 | assert(mints[0]['chain'] == "celo") 136 | assert(mints[0]['version'] == 1) 137 | assert(mints[0]['user'] != "") 138 | assert(mints[0]['token0'] != "") 139 | assert(mints[0]['token1'] != "") 140 | assert(mints[0]['pool'] != "") 141 | assert(float(mints[0]['amount0']) > 0) 142 | assert(float(mints[0]['amount1']) > 0) 143 | assert(float(mints[0]['timestamp']) > 0) 144 | 145 | 146 | def test_mint_quickswap_1_polygon(): 147 | quickswap = Dex(protocol="quickswap", chain="polygon", version=1) 148 | mints = quickswap.get_data_from_date_range( 149 | '30/09/2021 00:00:00', '30/09/2021 01:00:30', "mint") 150 | 151 | assert(mints[0]['tx_id'] != "") 152 | assert(mints[0]['protocol'] == "quickswap") 153 | assert(mints[0]['chain'] == "polygon") 154 | assert(mints[0]['version'] == 1) 155 | assert(mints[0]['user'] != "") 156 | assert(mints[0]['token0'] != "") 157 | assert(mints[0]['token1'] != "") 158 | assert(mints[0]['pool'] != "") 159 | assert(float(mints[0]['amount0']) > 0) 160 | assert(float(mints[0]['amount1']) > 0) 161 | assert(float(mints[0]['timestamp']) > 0) 162 | 163 | 164 | def test_mint_pangolin_1_avalanche(): 165 | pangolin = Dex(protocol="pangolin", chain="avalanche", version=1) 166 | mints = pangolin.get_data_from_date_range( 167 | '30/09/2021 00:00:00', '30/09/2021 01:00:30', "mint") 168 | 169 | assert(mints[0]['tx_id'] != "") 170 | assert(mints[0]['protocol'] == "pangolin") 171 | assert(mints[0]['chain'] == "avalanche") 172 | assert(mints[0]['version'] == 1) 173 | assert(mints[0]['user'] != "") 174 | assert(mints[0]['token0'] != "") 175 | assert(mints[0]['token1'] != "") 176 | assert(mints[0]['pool'] != "") 177 | assert(float(mints[0]['amount0']) > 0) 178 | assert(float(mints[0]['amount1']) > 0) 179 | assert(float(mints[0]['timestamp']) > 0) 180 | -------------------------------------------------------------------------------- /tests/unit/test_dex.py: -------------------------------------------------------------------------------- 1 | from deficrawler.dex import Dex 2 | 3 | 4 | def test_protocol_entities(): 5 | uniswap = Dex(protocol="Uniswap", chain="Ethereum", version=2) 6 | balancer = Dex(protocol="Balancer", chain="Ethereum", version=1) 7 | 8 | assert(uniswap.supported_entities() == [ 9 | 'swap', 'pool']) 10 | assert(balancer.supported_entities() == [ 11 | 'swap', 'pool']) 12 | -------------------------------------------------------------------------------- /tests/unit/test_lending.py: -------------------------------------------------------------------------------- 1 | from deficrawler.lending import Lending 2 | 3 | 4 | def test_protocol_entities(): 5 | aave = Lending(protocol="Aave", chain="Ethereum", version=2) 6 | compound = Lending(protocol="Compound", chain="Ethereum", version=2) 7 | 8 | assert(aave.supported_entities() == [ 9 | 'borrow', 'deposit', 'liquidation', 'repay']) 10 | assert(compound.supported_entities() == [ 11 | 'borrow', 'deposit', 'liquidation', 'repay']) 12 | -------------------------------------------------------------------------------- /tests/unit/test_protocol_base.py: -------------------------------------------------------------------------------- 1 | from deficrawler.protocol_base import ProtocolBase 2 | 3 | import pytest 4 | 5 | 6 | def test_protocol_not_exits(): 7 | with pytest.raises(Exception) as execinfo: 8 | ProtocolBase(protocol="NA", version=12, chain="other") 9 | 10 | assert execinfo.value.args[0] == 'Protocol NA version 12 not supported' 11 | 12 | 13 | def test_enpoint_not_exits(): 14 | with pytest.raises(Exception) as execinfo: 15 | ProtocolBase(protocol="Aave", version=2, chain="other") 16 | 17 | assert execinfo.value.args[0] == 'Protocol Aave chain other not supported' 18 | 19 | 20 | def test_entity_not_exits(): 21 | with pytest.raises(Exception) as execinfo: 22 | protocol = ProtocolBase(protocol="Compound", version=2, chain="Ethereum") 23 | protocol.get_protocol_config('swap') 24 | 25 | assert execinfo.value.args[0] == 'Entity swap not supported for protocol Compound' 26 | 27 | 28 | def test_protocol_exits(): 29 | protocol = ProtocolBase(protocol="Compound", version=2, chain="Ethereum") 30 | config = protocol.get_protocol_config('borrow') 31 | assert('attributes' in config) 32 | assert('transformations' in config) 33 | assert('query_elements' in config) 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /tests/unit/test_utils.py: -------------------------------------------------------------------------------- 1 | from deficrawler.utils import format_attribute, format_element, get_attributes, get_filters 2 | 3 | import pkgutil 4 | import json 5 | 6 | 7 | def test_get_filters(): 8 | filters_empty = get_filters('') 9 | assert(filters_empty == '') 10 | 11 | one_filter = get_filters({"user": "account"}) 12 | assert(one_filter == "user:\"account\"\n") 13 | 14 | several_filtes = get_filters({"user": "account", "pair": "assetPair"}) 15 | assert(several_filtes == "user:\"account\"\npair:\"assetPair\"\n") 16 | 17 | 18 | def test_format_element(): 19 | one_element = ["id"] 20 | one_formatted = format_element(one_element) 21 | assert(one_formatted == "id") 22 | 23 | two_elements = ["user", "id"] 24 | two_formatted = format_element(two_elements) 25 | assert(two_formatted == "user{id}") 26 | 27 | three_elements = ["pair", "token", "symbol"] 28 | three_formatted = format_element(three_elements) 29 | assert(three_formatted == "pair{token{symbol}}") 30 | 31 | 32 | def test_format_attribute(): 33 | one_attribute = ["sender"] 34 | one_formatted = format_attribute(one_attribute) 35 | assert(one_formatted == "sender") 36 | 37 | two_attribute = [ 38 | [ 39 | "pair", 40 | "token0", 41 | "symbol" 42 | ], 43 | [ 44 | "pair", 45 | "token1", 46 | "symbol" 47 | ] 48 | ] 49 | 50 | two_formatted = format_attribute(two_attribute) 51 | assert(two_formatted == "pair{token0{symbol}} pair{token1{symbol}} ") 52 | 53 | 54 | def test_get_attributes(): 55 | config_file = pkgutil.get_data( 56 | 'deficrawler.config', 57 | 'aave' + "-" + str('2') + ".json" 58 | ) 59 | 60 | map_file = json.loads(config_file.decode()) 61 | borrow_attr = get_attributes('borrow', map_file) 62 | print(borrow_attr == "reserve{decimals} id user{id} reserve{symbol} amount timestamp ") 63 | 64 | config_file = pkgutil.get_data( 65 | 'deficrawler.config', 66 | 'uniswap' + "-" + str('2') + ".json" 67 | ) 68 | 69 | map_file = json.loads(config_file.decode()) 70 | swap_attr = get_attributes('swap', map_file) 71 | assert(swap_attr =="sender transaction{id} pair{token0{symbol}} pair{token1{symbol}} pair{token0{symbol}} pair{token1{symbol}} amount0In amount1In amount0Out amount1Out pair{id} amountUSD timestamp ") 72 | 73 | --------------------------------------------------------------------------------