Adapter

Aave Fees

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.

Adapter Info

Version

0.1.1

License

MIT

IPFS CID

QmbSvMUTzjJopHEYhbwj8f1hyLANJgPeYk2fnAY4RSJBJR

CID (source)

Qmc4UW9n3PaUNcva1GM7SR79ZWUKT3ofuwZzsrVvVvBevm

Collections

fees

Author

mihal.eth