Sub-Adapters 5
Preview and test each sub adapter.
Aave - Version 1 (aave-v1)
Aave - Version 2 (aave-v2)
Aave - Version 2 - AMM (aave-v2-amm)
Aave - Version 2 - Polygon (aave-v2-polygon-proto)
Aave - Version 2 - Avalanche (aave-v2-avalanche-proto)
Adapter Code
Check the entire code written for the Adapter.
Source code
Showing TS source.
1export const name = 'Aave Fees';
2export const version = '0.1.1';
3export const license = 'MIT';
4
5type V1Reserve = {
6 lifetimeFlashloanDepositorsFee: string
7 lifetimeFlashloanProtocolFee: string
8 lifetimeOriginationFee: string
9 lifetimeDepositorsInterestEarned: string
10 priceInUsd: string
11 reserve: {
12 decimals: number
13 symbol: string
14 }
15}
16
17type V2Reserve = {
18 lifetimeFlashLoanPremium: string
19 lifetimeReserveFactorAccrued: string
20 lifetimeDepositorsInterestEarned: string
21 priceInUsd: string
22 reserve: {
23 decimals: number
24 symbol: string
25 }
26}
27
28const SUBGRAPHS = {
29 V1: 'aave/protocol-multy-raw',
30 V2: 'aave/protocol-v2',
31 POLYGON: 'aave/aave-v2-matic',
32 AVALANCHE: 'aave/protocol-v2-avalanche',
33}
34
35const POOL_IDS = {
36 V1: '0x24a42fd28c976a61df5d00d0599c34c4f90748c8',
37 V2: '0xb53c1a33016b2dc2ff3653530bff1848a515c8c5',
38 V2_AMM: '0xacc030ef66f9dfeae9cbb0cd1b25654b82cfa8d5',
39 POLYGON: '0xd05e3e715d945b59290df0ae8ef85c1bdb684744',
40 AVALANCHE: '0xb6a86025f0fe1862b372cb0ca18ce3ede02a318f',
41}
42
43export function setup(sdk: Context) {
44 async function getV1ReservesSnapshot(poolId: string, timestamp: number) {
45 const query = `{
46 reserves(where: { pool: "${poolId}" }) {
47 id
48 paramsHistory(where: { timestamp_lte: ${timestamp} }, orderBy: "timestamp", orderDirection: "desc", first: 1) {
49 id
50 priceInUsd
51 reserve {
52 decimals
53 symbol
54 }
55 lifetimeFlashloanDepositorsFee
56 lifetimeFlashloanProtocolFee
57 lifetimeOriginationFee
58 lifetimeDepositorsInterestEarned
59 }
60 }
61 }`;
62
63 const result = await sdk.graph.query(SUBGRAPHS.V1, query)
64
65 const reserves = result.reserves
66 .map((r: any) => r.paramsHistory[0])
67 .filter((r: any) => r)
68
69 return reserves
70 }
71
72 function calculateV1Fees(startReserves: V1Reserve[], endReserves: V1Reserve[]) {
73 return endReserves.reduce((acc: number, reserve: V1Reserve) => {
74 const startReserve = startReserves
75 .find((r: any) => r.reserve.symbol === reserve.reserve.symbol)
76
77 if (!startReserve) {
78 return 0;
79 }
80
81 const priceInUsd = parseFloat(reserve.priceInUsd);
82
83 const depositorInterest = parseFloat(reserve.lifetimeDepositorsInterestEarned)
84 - (parseFloat(startReserve?.lifetimeDepositorsInterestEarned) || 0);
85 const depositorInterestUSD = depositorInterest * priceInUsd / (10 ** reserve.reserve.decimals);
86
87 const originationFees = parseFloat(reserve.lifetimeOriginationFee)
88 - (parseFloat(startReserve?.lifetimeOriginationFee) || 0);
89 const originationFeesUSD = originationFees * priceInUsd / (10 ** reserve.reserve.decimals);
90
91 const flashloanDepositorsFees = parseFloat(reserve.lifetimeFlashloanDepositorsFee)
92 - (parseFloat(startReserve?.lifetimeFlashloanDepositorsFee) || 0);
93 const flashloanDepositorsFeesUSD = flashloanDepositorsFees * priceInUsd / (10 ** reserve.reserve.decimals);
94
95 const flashloanProtocolFees = parseFloat(reserve.lifetimeFlashloanProtocolFee)
96 - (parseFloat(startReserve?.lifetimeFlashloanProtocolFee) || 0);
97 const flashloanProtocolFeesUSD = flashloanProtocolFees * priceInUsd / (10 ** reserve.reserve.decimals);
98
99 return acc
100 + depositorInterestUSD
101 + originationFeesUSD
102 + flashloanProtocolFeesUSD
103 + flashloanDepositorsFeesUSD;
104 }, 0);
105 }
106
107 const getV1Fees = async (date: string): Promise<number> => {
108 const poolId = POOL_IDS.V1;
109 const startTimestamp = sdk.date.dateToTimestamp(date);
110 const nextDayTimestamp = sdk.date.dateToTimestamp(sdk.date.offsetDaysFormatted(date, 1));
111
112 const startReserves = await getV1ReservesSnapshot(poolId, startTimestamp);
113 const endReserves = await getV1ReservesSnapshot(poolId, nextDayTimestamp);
114
115 return calculateV1Fees(startReserves, endReserves);
116 }
117
118 ////
119 // V2 deployments
120 ////
121
122 async function getV2ReservesSnapshot(poolId: string, timestamp: number, subgraph: string) {
123 const query = `{
124 reserves(where: { pool: "${poolId}" }) {
125 id
126 paramsHistory(where: { timestamp_lte: ${timestamp} }, orderBy: "timestamp", orderDirection: "desc", first: 1) {
127 id
128 priceInEth
129 priceInUsd
130 reserve {
131 decimals
132 symbol
133 }
134 lifetimeFlashLoanPremium
135 lifetimeReserveFactorAccrued
136 lifetimeDepositorsInterestEarned
137 }
138 }
139 }`;
140
141 const result = await sdk.graph.query(subgraph, query)
142
143 const reserves = result.reserves
144 .map((r: any) => r.paramsHistory[0])
145 .filter((r: any) => r)
146
147 return reserves
148 }
149
150 function calculateV2Fees(startReserves: V2Reserve[], endReserves: V2Reserve[], usdPriceFeed?: boolean) {
151 return endReserves.reduce((acc: number, reserve: V2Reserve) => {
152 const startReserve = startReserves
153 .find((r: any) => r.reserve.symbol === reserve.reserve.symbol)
154
155 if (!startReserve) {
156 return 0;
157 }
158
159 const priceInUsd = usdPriceFeed
160 ? parseFloat(reserve.priceInUsd) / (10 ** 8)
161 : parseFloat(reserve.priceInUsd)
162
163 const depositorInterest = parseFloat(reserve.lifetimeDepositorsInterestEarned)
164 - (parseFloat(startReserve?.lifetimeDepositorsInterestEarned) || 0);
165 const depositorInterestUSD = depositorInterest * priceInUsd / (10 ** reserve.reserve.decimals);
166
167 const flashloanPremium = parseFloat(reserve.lifetimeFlashLoanPremium)
168 - (parseFloat(startReserve?.lifetimeFlashLoanPremium) || 0);
169 const flashloanPremiumUSD = flashloanPremium * priceInUsd / (10 ** reserve.reserve.decimals);
170
171 const reserveFactor = parseFloat(reserve.lifetimeReserveFactorAccrued)
172 - (parseFloat(startReserve?.lifetimeReserveFactorAccrued) || 0);
173 const reserveFactorUSD = reserveFactor * priceInUsd / (10 ** reserve.reserve.decimals);
174
175 return acc
176 + depositorInterestUSD
177 + flashloanPremiumUSD
178 + reserveFactorUSD;
179 }, 0);
180 }
181
182 const getV2Fees = (
183 poolId: string,
184 subgraph: string,
185 usdPriceFeed?: boolean
186 ) => async (date: string): Promise<number> => {
187 const startTimestamp = sdk.date.dateToTimestamp(date);
188 const nextDayTimestamp = sdk.date.dateToTimestamp(sdk.date.offsetDaysFormatted(date, 1));
189
190 const startReserves = await getV2ReservesSnapshot(poolId, startTimestamp, subgraph);
191 const endReserves = await getV2ReservesSnapshot(poolId, nextDayTimestamp, subgraph);
192
193 return calculateV2Fees(startReserves, endReserves, usdPriceFeed);
194 }
195
196 const metadata = {
197 name: 'Aave',
198 icon: sdk.ipfs.getDataURILoader('QmW4X8Q36jjPm8fzU21NzFKRxNzReQy4JnehKbRrgybFh6', 'image/svg+xml'),
199 category: 'lending',
200 description:
201 'Aave is an open source and non-custodial liquidity protocol for earning interest on deposits and borrowing assets.',
202 feeDescription:
203 'Fees are accrued from the dynamics of providing liquidity and borrowing, going to liquidity suppliers and the Aave DAO treasury.',
204 blockchain: 'Ethereum',
205 source: 'The Graph Protocol',
206 website: 'https://aave.com',
207 tokenTicker: 'AAVE',
208 tokenCoingecko: 'aave',
209 tokenLaunch: '2020-09-14', // TODO: add real token launch data
210 protocolLaunch: '2020-01-08',
211 };
212
213 sdk.registerBundle('aave', metadata);
214
215 sdk.register({
216 id: 'aave-v1',
217 bundle: 'aave',
218 queries: {
219 oneDayTotalFees: getV1Fees,
220 },
221 metadata: {
222 ...metadata,
223 subtitle: 'Version 1',
224 protocolLaunch: '2020-01-08',
225 },
226 });
227
228 sdk.register({
229 id: 'aave-v2',
230 bundle: 'aave',
231 queries: {
232 oneDayTotalFees: getV2Fees(POOL_IDS.V2, SUBGRAPHS.V2),
233 },
234 metadata: {
235 ...metadata,
236 subtitle: 'Version 2',
237 protocolLaunch: '2020-12-03',
238 },
239 });
240
241 sdk.register({
242 id: 'aave-v2-amm',
243 bundle: 'aave',
244 queries: {
245 oneDayTotalFees: getV2Fees(POOL_IDS.V2_AMM, SUBGRAPHS.V2),
246 },
247 metadata: {
248 ...metadata,
249 subtitle: 'Version 2 - AMM',
250 protocolLaunch: '2021-03-08',
251 },
252 });
253
254 sdk.register({
255 id: 'aave-v2-polygon-proto',
256 bundle: 'aave',
257 queries: {
258 oneDayTotalFees: getV2Fees(POOL_IDS.POLYGON, SUBGRAPHS.POLYGON),
259 },
260 metadata: {
261 ...metadata,
262 subtitle: 'Version 2 - Polygon',
263 protocolLaunch: '2021-03-31',
264 blockchain: 'Polygon',
265 },
266 });
267
268 sdk.register({
269 id: 'aave-v2-avalanche-proto',
270 bundle: 'aave',
271 queries: {
272 oneDayTotalFees: getV2Fees(POOL_IDS.AVALANCHE, SUBGRAPHS.AVALANCHE, true),
273 },
274 metadata: {
275 ...metadata,
276 subtitle: 'Version 2 - Avalanche',
277 protocolLaunch: '2021-10-04',
278 blockchain: 'Avalanche',
279 },
280 });
281}
282
It's something off?
Report it to the discussion board on Discord, we will take care of it.