Skip to content

Commit a2ca23a

Browse files
feat: add supply and borrow time series to the isolated pools subgraph
1 parent 68f1cb9 commit a2ca23a

File tree

8 files changed

+442
-226
lines changed

8 files changed

+442
-226
lines changed

subgraphs/isolated-pools/schema.graphql

Lines changed: 292 additions & 213 deletions
Large diffs are not rendered by default.

subgraphs/isolated-pools/src/mappings/vToken.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
ReservesAdded,
1818
SpreadReservesReduced,
1919
Transfer,
20+
VToken,
2021
} from '../../generated/PoolRegistry/VToken';
2122
import { VToken as VTokenContract } from '../../generated/PoolRegistry/VToken';
2223
import { nullAddress } from '../constants/addresses';
@@ -31,12 +32,14 @@ import {
3132
createTransferTransaction,
3233
} from '../operations/create';
3334
import { getMarket } from '../operations/get';
34-
import { getOrCreateAccount } from '../operations/getOrCreate';
35+
import { getOrCreateAccount, getOrCreateToken } from '../operations/getOrCreate';
3536
import {
3637
updateMarketPositionBorrow,
3738
updateMarketPositionSupply,
3839
updateMarket,
3940
} from '../operations/update';
41+
import { updateMarketRates } from '../operations/updateMarketRates';
42+
import getTokenPriceInCents from '../utilities/getTokenPriceInCents';
4043

4144
/* Account supplies assets into market and receives vTokens in exchange
4245
*
@@ -329,6 +332,16 @@ export function handleReservesAdded(event: ReservesAdded): void {
329332
const market = getMarket(vTokenAddress);
330333
if (market) {
331334
market.reservesMantissa = event.params.newTotalReserves;
335+
336+
const marketContract = VToken.bind(vTokenAddress);
337+
const underlyingToken = getOrCreateToken(Address.fromBytes(market.underlyingToken));
338+
const underlyingPriceCents = getTokenPriceInCents(
339+
Address.fromBytes(market.pool),
340+
vTokenAddress,
341+
underlyingToken.decimals,
342+
);
343+
updateMarketRates(market, marketContract, underlyingPriceCents, event.block.number);
344+
332345
market.save();
333346
}
334347
}
@@ -338,6 +351,16 @@ export function handleSpreadReservesReduced(event: SpreadReservesReduced): void
338351
const market = getMarket(vTokenAddress);
339352
if (market) {
340353
market.reservesMantissa = event.params.newTotalReserves;
354+
355+
const marketContract = VToken.bind(vTokenAddress);
356+
const underlyingToken = getOrCreateToken(Address.fromBytes(market.underlyingToken));
357+
const underlyingPriceCents = getTokenPriceInCents(
358+
Address.fromBytes(market.pool),
359+
vTokenAddress,
360+
underlyingToken.decimals,
361+
);
362+
updateMarketRates(market, marketContract, underlyingPriceCents, event.block.number);
363+
341364
market.save();
342365
}
343366
}

subgraphs/isolated-pools/src/operations/create.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ import {
2323
Pool,
2424
RewardsDistributor,
2525
Transaction,
26+
MarketRatesData,
27+
MarketSupplyPositionData,
28+
MarketBorrowPositionData,
2629
} from '../../generated/schema';
2730
import { Comptroller } from '../../generated/templates/Pool/Comptroller';
2831
import { RewardsDistributor as RewardDistributorContract } from '../../generated/templates/RewardsDistributor/RewardsDistributor';
@@ -341,3 +344,49 @@ export function createRewardDistributor(
341344
}
342345
return rewardsDistributor;
343346
}
347+
348+
export function createMarketRatesData(
349+
marketAddress: Address,
350+
blockNumber: BigInt,
351+
exchangeRateMantissa: BigInt,
352+
supplyRateMantissa: BigInt,
353+
borrowRateMantissa: BigInt,
354+
underlyingPriceCents: BigInt,
355+
): void {
356+
const marketRatesEntity = new MarketRatesData('auto');
357+
marketRatesEntity.market = marketAddress;
358+
marketRatesEntity.exchangeRateMantissa = exchangeRateMantissa;
359+
marketRatesEntity.supplyRateMantissa = supplyRateMantissa;
360+
marketRatesEntity.borrowRateMantissa = borrowRateMantissa;
361+
marketRatesEntity.blockNumber = blockNumber;
362+
marketRatesEntity.underlyingPriceCents = underlyingPriceCents;
363+
marketRatesEntity.save();
364+
}
365+
366+
export function createMarketSupplyPositionData(
367+
marketAddress: Address,
368+
accountAddress: Address,
369+
blockNumber: BigInt,
370+
vTokenBalanceMantissa: BigInt,
371+
): void {
372+
const marketSupplyPositionEntity = new MarketSupplyPositionData('auto');
373+
marketSupplyPositionEntity.market = marketAddress;
374+
marketSupplyPositionEntity.account = accountAddress;
375+
marketSupplyPositionEntity.blockNumber = blockNumber;
376+
marketSupplyPositionEntity.vTokenBalanceMantissa = vTokenBalanceMantissa;
377+
marketSupplyPositionEntity.save();
378+
}
379+
380+
export function createMarketBorrowPositionData(
381+
marketAddress: Address,
382+
accountAddress: Address,
383+
blockNumber: BigInt,
384+
borrowBalanceMantissa: BigInt,
385+
): void {
386+
const marketBorrowPositionEntity = new MarketBorrowPositionData('auto');
387+
marketBorrowPositionEntity.market = marketAddress;
388+
marketBorrowPositionEntity.account = accountAddress;
389+
marketBorrowPositionEntity.blockNumber = blockNumber;
390+
marketBorrowPositionEntity.borrowBalanceMantissa = borrowBalanceMantissa;
391+
marketBorrowPositionEntity.save();
392+
}

subgraphs/isolated-pools/src/operations/update.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {
1313
getOrCreateToken,
1414
} from './getOrCreate';
1515
import { oneBigInt, zeroBigInt32 } from '../constants';
16+
import { updateMarketRates } from './updateMarketRates';
17+
import { createMarketSupplyPositionData } from './create';
1618

1719
export const updateMarketPositionAccrualBlockNumber = (
1820
accountAddress: Address,
@@ -49,11 +51,19 @@ export const updateMarketPositionSupply = (
4951
Address.fromBytes(market.pool),
5052
blockNumber,
5153
);
54+
5255
if (marketPosition) {
5356
const _vTokenBalanceMantissa = marketPosition.vTokenBalanceMantissa;
5457
marketPosition.vTokenBalanceMantissa = accountSupplyBalanceMantissa;
5558
marketPosition.save();
5659

60+
createMarketSupplyPositionData(
61+
marketAddress,
62+
accountAddress,
63+
blockNumber,
64+
accountSupplyBalanceMantissa,
65+
);
66+
5767
if (
5868
_vTokenBalanceMantissa.equals(zeroBigInt32) &&
5969
accountSupplyBalanceMantissa.notEqual(zeroBigInt32)
@@ -86,13 +96,16 @@ export const updateMarketPositionBorrow = (
8696
Address.fromBytes(market.pool),
8797
blockNumber,
8898
);
99+
89100
if (marketPosition) {
90101
const _storedBorrowBalanceMantissa = marketPosition.storedBorrowBalanceMantissa;
91102
marketPosition.storedBorrowBalanceMantissa = accountBorrows;
92103
const vTokenContract = VToken.bind(marketAddress);
93104
marketPosition.borrowIndex = vTokenContract.borrowIndex();
94105
marketPosition.save();
95106

107+
updateMarketPositionBorrow(accountAddress, marketAddress, blockNumber, accountBorrows);
108+
96109
if (
97110
_storedBorrowBalanceMantissa.equals(zeroBigInt32) &&
98111
accountBorrows.notEqual(zeroBigInt32)
@@ -134,23 +147,12 @@ export const updateMarket = (vTokenAddress: Address, blockNumber: BigInt): Marke
134147
marketContract.try_accrualBlockNumber(),
135148
);
136149

137-
const exchangeRateMantissa = valueOrNotAvailableIntIfReverted(
138-
marketContract.try_exchangeRateStored(),
139-
);
140-
market.exchangeRateMantissa = exchangeRateMantissa;
141-
142150
market.reservesMantissa = valueOrNotAvailableIntIfReverted(marketContract.try_totalReserves());
143151

144152
const cashBigInt = valueOrNotAvailableIntIfReverted(marketContract.try_getCash());
145153
market.cashMantissa = cashBigInt;
146154

147-
// calling supplyRatePerBlock & borrowRatePerBlock can fail due to external reasons, so we fall back to 0 in case of an error
148-
market.borrowRateMantissa = valueOrNotAvailableIntIfReverted(
149-
marketContract.try_borrowRatePerBlock(),
150-
);
151-
market.supplyRateMantissa = valueOrNotAvailableIntIfReverted(
152-
marketContract.try_supplyRatePerBlock(),
153-
);
155+
updateMarketRates(market, marketContract, tokenPriceCents, blockNumber);
154156

155157
market.save();
156158
return market;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { BigInt } from '@graphprotocol/graph-ts';
2+
import { Market } from '../../generated/schema';
3+
import { VToken } from '../../generated/templates/VToken/VToken';
4+
import { valueOrNotAvailableIntIfReverted } from '../utilities';
5+
6+
export function updateMarketBorrowRate(market: Market, vTokenContract: VToken): BigInt {
7+
market.borrowRateMantissa = valueOrNotAvailableIntIfReverted(
8+
vTokenContract.try_borrowRatePerBlock(),
9+
);
10+
return market.borrowRateMantissa;
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { BigInt } from '@graphprotocol/graph-ts';
2+
import { Market } from '../../generated/schema';
3+
import { VToken } from '../../generated/templates/VToken/VToken';
4+
import { valueOrNotAvailableIntIfReverted } from '../utilities';
5+
6+
export function updateMarketExchangeRate(market: Market, vTokenContract: VToken): BigInt {
7+
market.exchangeRateMantissa = valueOrNotAvailableIntIfReverted(
8+
vTokenContract.try_exchangeRateStored(),
9+
);
10+
return market.exchangeRateMantissa;
11+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Address, BigInt } from '@graphprotocol/graph-ts';
2+
import { Market } from '../../generated/schema';
3+
import { VToken } from '../../generated/templates/VToken/VToken';
4+
import { createMarketRatesData } from './create';
5+
import { updateMarketBorrowRate } from './updateMarketBorrowRate';
6+
import { updateMarketExchangeRate } from './updateMarketExchangeRate';
7+
import { updateMarketSupplyRate } from './updateMarketSupplyRate';
8+
9+
// if an event updated the market reserves, it means we need to update the market rates that depend on it:
10+
// borrow rate, supply rate and the exchange rate
11+
export function updateMarketRates(
12+
market: Market,
13+
vTokenContract: VToken,
14+
underlyingPriceCents: BigInt,
15+
blockNumber: BigInt,
16+
): void {
17+
const borrowRate = updateMarketBorrowRate(market, vTokenContract);
18+
const supplyRate = updateMarketSupplyRate(market, vTokenContract);
19+
const exchangeRate = updateMarketExchangeRate(market, vTokenContract);
20+
21+
createMarketRatesData(
22+
Address.fromBytes(market.address),
23+
blockNumber,
24+
exchangeRate,
25+
supplyRate,
26+
borrowRate,
27+
underlyingPriceCents,
28+
);
29+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { BigInt } from '@graphprotocol/graph-ts';
2+
import { Market } from '../../generated/schema';
3+
import { VToken } from '../../generated/templates/VToken/VToken';
4+
import { valueOrNotAvailableIntIfReverted } from '../utilities';
5+
6+
export function updateMarketSupplyRate(market: Market, vTokenContract: VToken): BigInt {
7+
market.supplyRateMantissa = valueOrNotAvailableIntIfReverted(
8+
vTokenContract.try_supplyRatePerBlock(),
9+
);
10+
11+
return market.supplyRateMantissa;
12+
}

0 commit comments

Comments
 (0)