|
1 | | -# Subgraph for Aave Protocol V2 |
2 | 1 |
|
| 2 | +# Aave Protocol Subgraphs |
| 3 | + |
| 4 | +The Aave Protocol subgraphs index data from the protocol smart contracts, and expose a GraphQL endpoint hosted by [The Graph](https://thegraph.com). |
| 5 | + |
| 6 | +- [Active Deployments](#active-deployments) |
| 7 | +- [Usage](#usage) |
| 8 | +- [Development](#deployment) |
| 9 | + |
| 10 | + |
3 | 11 | ## Active deployments |
4 | | -- [mainnet](https://thegraph.com/hosted-service/subgraph/aave/protocol-v2) |
5 | | -- [polygon](https://thegraph.com/hosted-service/subgraph/aave/aave-v2-matic) |
6 | | -- [avalanche](https://thegraph.com/hosted-service/subgraph/aave/protocol-v2-avalanche) |
7 | | -- [Polygon V3](https://thegraph.com/hosted-service/subgraph/aave/protocol-v3-polygon) |
8 | | -- [Avalanche V3](https://thegraph.com/hosted-service/subgraph/aave/protocol-v3-avalanche) |
9 | | -- [Arbitrum V3](https://thegraph.com/hosted-service/subgraph/aave/protocol-v3-arbitrum) |
10 | | -- [Optimism V3](https://thegraph.com/hosted-service/subgraph/aave/protocol-v3-optimism) |
11 | | -- [Fantom V3](https://thegraph.com/hosted-service/subgraph/aave/protocol-v3-fantom) |
12 | | -- Harmony V3 not supported |
| 12 | +- [ETH Mainnet V2](https://thegraph.com/hosted-service/subgraph/aave/protocol-v2) |
| 13 | +- [Polygon V2](https://thegraph.com/hosted-service/subgraph/aave/aave-v2-matic) |
| 14 | +- [Avalanche V2](https://thegraph.com/hosted-service/subgraph/aave/protocol-v2-avalanche) |
| 15 | +- [Polygon V3](https://thegraph.com/hosted-service/subgraph/aave/protocol-v3-polygon) |
| 16 | +- [Avalanche V3](https://thegraph.com/hosted-service/subgraph/aave/protocol-v3-avalanche) |
| 17 | +- [Arbitrum V3](https://thegraph.com/hosted-service/subgraph/aave/protocol-v3-arbitrum) |
| 18 | +- [Optimism V3](https://thegraph.com/hosted-service/subgraph/aave/protocol-v3-optimism) |
| 19 | +- [Fantom V3](https://thegraph.com/hosted-service/subgraph/aave/protocol-v3-fantom) |
| 20 | +- TheGraph is not available yet on Harmony |
| 21 | + |
| 22 | +## Usage |
| 23 | + |
| 24 | +Subgraphs can be queried directly from the graph explorer, or from [another application](https://thegraph.com/docs/en/developer/querying-from-your-app/). The following section gives common queries for Aave protocol data. |
| 25 | + |
| 26 | +### Queries |
| 27 | + |
| 28 | +See [TheGraph API](https://thegraph.com/docs/en/developer/graphql-api/) docs for a complete guide on querying capabilities. |
| 29 | + |
| 30 | +<details> |
| 31 | + <summary>Reserve Data</summary> |
| 32 | + |
| 33 | +#### Reserve Summary |
| 34 | + |
| 35 | +The `reserve` entity gives data on the assets of the protocol including rates, configuration, and total supply/borrow amounts. |
| 36 | + |
| 37 | +The aave-utilities library includes a [`formatReserves`](https://github.com/aave/aave-utilities/#formatReserves) function which can be used to format all data into a human readable format. The queries to fetch data for passing into this function can be found [here](https://github.com/aave/aave-utilities#subgraph). |
| 38 | + |
| 39 | + |
| 40 | +Why does the raw subgraph data not match app.aave.com? |
| 41 | + |
| 42 | + - aToken and debtToken balances are continuously increasing. The subgraph provides a snapshot of the balance at the time of indexing (not querying), which means fields affected by interest such as `totalLiquidity`, `availableLiquidity`, and `totalCurrentVariableDebt` will need to be formatted to get real-time values |
| 43 | + - All rates (liquidityRate, variableBorrowRate, stableBorrowRate) are expressed as *APR* with RAY units (10**27). To convert to the APY percentage as shown on the Aave frontend: `supplyAPY = (((1 + ((liquidityRate / 10**27) / 31536000)) ^ 31536000) - 1) * 100`. [`formatReserves`](https://github.com/aave/aave-utilities/#formatReserves) will perform this calculation for you. |
| 44 | + |
| 45 | +</details> |
| 46 | + |
| 47 | + |
| 48 | +<details> |
| 49 | + <summary>User Data</summary> |
| 50 | + |
| 51 | +#### User Summary |
| 52 | + |
| 53 | +The `userReserve` entity gives the supply and borrow balances for a particular user along with the underlying reserve data. |
| 54 | + |
| 55 | +The aave-utilities library includes a [`formatUserSummary`](https://github.com/aave/aave-utilities#formatUserSummary) function which can be used to format all data into a human readable format. The queries to fetch data for passing into this function can be found [here](https://github.com/aave/aave-utilities#subgraph). |
| 56 | + |
| 57 | +Why does the raw subgraph data not match my account balances on app.aave.com? |
| 58 | + |
| 59 | + - aToken and debtToken balances are continuously increasing. The subgraph provides a snapshot of the balance at the time of indexing (not querying), which means fields affected by interest such as `currentATokenBalance`, `currentVariableDebt`, and `currentStableDebt` will need to be formatted to get the real-time values |
| 60 | + |
| 61 | + |
| 62 | +#### Transaction History |
| 63 | + |
| 64 | + |
| 65 | +The `pool` parameter is the LendingPoolAddressesProvider (V2) or PoolAddressesProvider (V3) address which you can get from the [deployed contracts](https://docs.aave.com/developers/deployed-contracts/deployed-contracts) page. |
| 66 | + |
| 67 | +``` |
| 68 | +userTransactions( |
| 69 | + where: { user: "lowercase_user_address", pool: "lowercase_pool_addresses_provider" } |
| 70 | + orderBy: timestamp |
| 71 | + orderDirection: desc |
| 72 | + ) { |
| 73 | + id |
| 74 | + timestamp |
| 75 | + ... on Deposit { |
| 76 | + amount |
| 77 | + reserve { |
| 78 | + symbol |
| 79 | + decimals |
| 80 | + } |
| 81 | + } |
| 82 | + ... on RedeemUnderlying { |
| 83 | + amount |
| 84 | + reserve { |
| 85 | + symbol |
| 86 | + decimals |
| 87 | + } |
| 88 | + } |
| 89 | + ... on Borrow { |
| 90 | + amount |
| 91 | + borrowRateMode |
| 92 | + borrowRate |
| 93 | + stableTokenDebt |
| 94 | + variableTokenDebt |
| 95 | + reserve { |
| 96 | + symbol |
| 97 | + decimals |
| 98 | + } |
| 99 | + } |
| 100 | + ... on UsageAsCollateral { |
| 101 | + fromState |
| 102 | + toState |
| 103 | + reserve { |
| 104 | + symbol |
| 105 | + } |
| 106 | + } |
| 107 | + ... on Repay { |
| 108 | + amount |
| 109 | + reserve { |
| 110 | + symbol |
| 111 | + decimals |
| 112 | + } |
| 113 | + } |
| 114 | + ... on Swap { |
| 115 | + borrowRateModeFrom |
| 116 | + borrowRateModeTo |
| 117 | + variableBorrowRate |
| 118 | + stableBorrowRate |
| 119 | + reserve { |
| 120 | + symbol |
| 121 | + decimals |
| 122 | + } |
| 123 | + } |
| 124 | + ... on LiquidationCall { |
| 125 | + collateralAmount |
| 126 | + collateralReserve { |
| 127 | + symbol |
| 128 | + decimals |
| 129 | + } |
| 130 | + principalAmount |
| 131 | + principalReserve { |
| 132 | + symbol |
| 133 | + decimals |
| 134 | + } |
| 135 | + } |
| 136 | + } |
| 137 | +``` |
| 138 | + |
| 139 | +</details> |
| 140 | + |
| 141 | +<details> |
| 142 | + <summary>Querying Tips</summary> |
| 143 | + |
| 144 | +### Historical Queries |
| 145 | + |
| 146 | +You can query for historical data by specifying a block number: |
| 147 | + |
| 148 | +``` |
| 149 | +{ |
| 150 | + reserves(block: {number: 14568297}){ |
| 151 | + symbol |
| 152 | + liquidityRate |
| 153 | + } |
| 154 | +} |
| 155 | +``` |
| 156 | + |
| 157 | +To query based on a historical timestamp, you will need to convert the timstamp to the most recent block number, you will need to use an external tool such as [this](https://www.npmjs.com/package/ethereum-block-by-date). |
| 158 | + |
| 159 | + |
| 160 | +### Pagination |
| 161 | + |
| 162 | + The Graph places a limit on the number of items which can returned by a single query (currently 100). To fetch a larger number of items, the `first` and `skip` parameters can be used to create paginated queries. |
| 163 | + |
| 164 | +For example, if you wanted to fetch the first 200 transactions for an Aave market, you can't query 200 items at once, but you can achieve the same thing by concatenating the output of these queries: |
| 165 | +``` |
| 166 | +{ |
| 167 | + userTransactions(orderBy: timestamp, orderDirection: asc, first: 100, skip: 0){ |
| 168 | + timestamp |
| 169 | + } |
| 170 | +} |
| 171 | +``` |
| 172 | +``` |
| 173 | +{ |
| 174 | + userTransactions(orderBy: timestamp, orderDirection: asc, first: 100, skip: 100){ |
| 175 | + timestamp |
| 176 | + } |
| 177 | +} |
| 178 | +``` |
| 179 | +</details> |
13 | 180 |
|
14 | 181 | ## Development |
15 | 182 |
|
16 | 183 | ```bash |
17 | | -# copy env and adjust its content |
| 184 | + |
| 185 | +# copy env and adjust its content with your personal access token and subgraph name |
| 186 | + |
18 | 187 | # you can get an access token from https://thegraph.com/explorer/dashboard |
19 | 188 | cp .env.test .env |
| 189 | + |
20 | 190 | # install project dependencies |
21 | 191 | npm i |
22 | | -# fetch current contracts as submodule |
23 | | -npm run prepare:all |
24 | | -# run codegen |
25 | | -npm run subgraph:codegen |
26 | | -# now you're able to deploy to thegraph via |
27 | | -npm run deploy:hosted:mainnet |
28 | | - |
29 | | -``` |
30 | | - |
31 | | -## Deployment |
32 | | - |
33 | | -To be able to deploy the subgraph in any environment for any network first we will need to prepare the local env: |
34 | | - |
35 | | -- get the protocol v2 contracts and compile them |
36 | | - |
37 | | -``` |
38 | | -npm run prepare:contracts |
39 | | -``` |
40 | | - |
41 | | -### Self-hosted |
42 | | - |
43 | | -- The first time you will deploy the subgraph you need to first create it in the TheGraph node: |
44 | | - |
45 | | -``` |
46 | | -// For Kovan: |
47 | | -npm run subgraph:create:self-hosted:kovan |
48 | | -
|
49 | | -// for Mainnet |
50 | | -npm run subgraph:create:self-hosted:mainnet |
51 | | -``` |
52 | | - |
53 | | -- Before any deployment you need to generate the types and schemas: |
54 | 192 |
|
55 | | -``` |
| 193 | +# to regenrate types if schema.graphql has changed |
56 | 194 | npm run subgraph:codegen |
57 | | -``` |
58 | | - |
59 | | -- When / If the subgraph is created you can then deploy |
60 | 195 |
|
61 | | -``` |
62 | | -// For Kovan: |
63 | | - npm run deploy:self-hosted:kovan |
| 196 | +# to run a test build of your subgraph |
| 197 | +npm run subgraph:build |
64 | 198 |
|
65 | | -// For Mainnet: |
66 | | - npm run deploy:self-hosted:mainnet |
67 | | -``` |
68 | | - |
69 | | -### Hosted |
70 | | - |
71 | | -To be able to deploy to the hosted solution you will need to create a .env file and add `ACCESS_TOKEN` environment variable. You can find this in the dashboard of the TheGraph |
72 | | - |
73 | | -``` |
74 | | -// For Kovan: |
75 | | -npm run deploy:hosted:kovan |
76 | | -
|
77 | | -// For Mainnet: |
| 199 | +# now you're able to deploy to thegraph hosted service with one of the deploy commands: |
78 | 200 | npm run deploy:hosted:mainnet |
79 | | -``` |
80 | | - |
81 | | -### Local |
82 | | - |
83 | | -TODO: |
84 | | - |
85 | | -- refactor get addresses after local deployment |
86 | | -- refactor npm scripts |
87 | 201 |
|
88 | | -1. Start docker environment for a buidler node and TheGraph infrastructure: |
89 | | - |
90 | | -``` |
91 | | -docker-compose up |
92 | 202 | ``` |
93 | 203 |
|
94 | | -Remember that before runing `docker-compose up` you need to run `docker-compose down` if it is not the first time. That is because the postgres database needs to not be persistant, so we need to delete the docker volumes. |
| 204 | +### Troubleshooting |
95 | 205 |
|
96 | | -2. Deploy local subgraph: |
| 206 | +If a subgraph encounters an error while indexing, the logs on the explorer may not display the error. You can check for errors on a pending or synced subgraph with the following commands, replacing `aave/protocol-v2` with your subgraph name: |
97 | 207 |
|
| 208 | +Pending: |
98 | 209 | ``` |
99 | | -
|
| 210 | +curl --location --request POST 'https://api.thegraph.com/index-node/graphql' --data-raw '{"query":"{ indexingStatusForPendingVersion(subgraphName: \"aave/protocol-v2\") { subgraph fatalError { message } nonFatalErrors {message } } }"}' |
100 | 211 | ``` |
101 | 212 |
|
102 | | -3. To check or query the subgraph use: |
| 213 | +Synced: |
103 | 214 |
|
104 | 215 | ``` |
105 | | -Queries (HTTP): http://localhost:8000/subgraphs/name/aave/migrator |
106 | | -Subscriptions (WS): http://localhost:8001/subgraphs/name/aave/migrator |
107 | | -
|
108 | | -INFO Starting JSON-RPC admin server at: http://localhost:8020, component: JsonRpcServer |
109 | | -INFO Starting GraphQL HTTP server at: http://localhost:8000, component: GraphQLServer |
110 | | -INFO Starting index node server at: http://localhost:8030, component: IndexNodeServer |
111 | | -INFO Starting GraphQL WebSocket server at: ws://localhost:8001, component: SubscriptionServer |
112 | | -INFO Starting metrics server at: http://localhost:8040, component: MetricsServer |
113 | | -
|
| 216 | +curl --location --request POST 'https://api.thegraph.com/index-node/graphql' --data-raw '{"query":"{ indexingStatusForCurrentVersion(subgraphName: \"aave/protocol-v2\") { subgraph fatalError { message } nonFatalErrors {message } } }"}' |
114 | 217 | ``` |
0 commit comments