Skip to content

Commit

Permalink
feat: add price and apr snapshots
Browse files Browse the repository at this point in the history
  • Loading branch information
yvesfracari committed Jan 14, 2025
1 parent 0e2c443 commit 119bd52
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 6 deletions.
10 changes: 10 additions & 0 deletions ponder.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ export default createConfig({
startBlock: FACTORY[baseSepolia.id].startBlock,
interval: (60 * 60) / 2, // 1 hour
},
PriceSnapshotUpdate: {
network: 'baseSepolia',
startBlock: FACTORY[baseSepolia.id].startBlock + 1, // plus one to get snapshot after price update
interval: (60 * 60 * 24) / 2, // 1 day
},
APRSnapshotUpdate: {
network: 'baseSepolia',
startBlock: FACTORY[baseSepolia.id].startBlock + 1, // plus one to get snapshot after price update
interval: (60 * 60 * 24) / 2, // 1 day
},
},
contracts: {
Factory: {
Expand Down
17 changes: 17 additions & 0 deletions relations.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
liquidateBorrow,
marketEntered,
marketExited,
priceSnapshot,
protocol,
pToken,
pTokenEMode,
Expand Down Expand Up @@ -100,6 +101,8 @@ export const pTokenRelations = relations(pToken, ({ one, many }) => ({
}),
userBalances: many(userBalance),
many: many(pTokenEMode),
priceSnapshots: many(priceSnapshot),
aprSnapshots: many(priceSnapshot),
}));

export const marketEnteredRelations = relations(marketEntered, ({ one }) => ({
Expand Down Expand Up @@ -347,3 +350,17 @@ export const userEModeRelations = relations(userEMode, ({ one }) => ({
references: [protocol.id],
}),
}));

export const priceSnapshotRelations = relations(priceSnapshot, ({ one }) => ({
pToken: one(pToken, {
fields: [priceSnapshot.pTokenId],
references: [pToken.id],
}),
}));

export const aprSnapshotRelations = relations(priceSnapshot, ({ one }) => ({
pToken: one(pToken, {
fields: [priceSnapshot.pTokenId],
references: [pToken.id],
}),
}));
32 changes: 31 additions & 1 deletion src/currentPriceUpdate.ts → src/block.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { ponder } from 'ponder:registry';
import { protocol, pToken } from 'ponder:schema';
import { aprSnapshot, priceSnapshot, protocol, pToken } from 'ponder:schema';
import { readMultiplePTokenPricesInfo } from './utils/multicalls';
import { formatEther } from 'viem';
import { MathSol } from './utils/math';
import { bigint, timestamp } from 'ponder';

ponder.on('CurrentPriceUpdate:block', async ({ context, event }) => {
// for some reason while using merge to do 1 SQL it return an error.
Expand Down Expand Up @@ -45,3 +46,32 @@ ponder.on('CurrentPriceUpdate:block', async ({ context, event }) => {
)
);
});

ponder.on('PriceSnapshotUpdate:block', async ({ context, event }) => {
const pTokens = await context.db.sql.select().from(pToken);

const snapshotValues = pTokens.map(ptoken => ({
id: `${ptoken.id}-${event.block.number}`,
pTokenId: ptoken.id,
price: ptoken.currentUnderlyingPrice,
timestamp: event.block.timestamp,
chainId: BigInt(context.network.chainId),
}));

await context.db.insert(priceSnapshot).values(snapshotValues);
});

ponder.on('APRSnapshotUpdate:block', async ({ context, event }) => {
const pTokens = await context.db.sql.select().from(pToken);

const snapshotValues = pTokens.map(ptoken => ({
id: `${ptoken.id}-${event.block.number}`,
pTokenId: ptoken.id,
supplyRatePerSecond: ptoken.supplyRatePerSecond,
borrowRatePerSecond: ptoken.borrowRatePerSecond,
timestamp: event.block.timestamp,
chainId: BigInt(context.network.chainId),
}));

await context.db.insert(aprSnapshot).values(snapshotValues);
});
12 changes: 9 additions & 3 deletions src/utils/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ import { config, EventNames } from 'ponder:registry';

export type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

export type ContractEvents = Exclude<EventNames, 'CurrentPriceUpdate:block'>;
export type BlockEventNames =
| 'CurrentPriceUpdate:block'
| 'PriceSnapshotUpdate:block'
| 'APRSnapshotUpdate:block';

export type ContractEvent<name extends ContractEvents = ContractEvents> =
Virtual.Event<config['default'], name>;
export type ContractEventsName = Exclude<EventNames, BlockEventNames>;

export type ContractEvent<
name extends ContractEventsName = ContractEventsName,
> = Virtual.Event<config['default'], name>;
3 changes: 1 addition & 2 deletions src/utils/underlying.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Context, Event } from 'ponder:registry';
import { Address } from 'viem';
import { getAddressId } from './id';
import { underlyingToken, pToken, protocol } from 'ponder:schema';
import { underlyingToken } from 'ponder:schema';
import { readErc20Information } from './multicalls';
import { OracleEngineAbi } from '../../abis/OracleEngineAbi';

export async function createIfNotExistsUnderlying(
address: Address,
Expand Down
17 changes: 17 additions & 0 deletions tables.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,20 @@ export const userBalance = onchainTable('user_balance', t => ({
borrowAssets: t.bigint().notNull().default(0n),
isCollateral: t.boolean().notNull().default(false),
}));

export const priceSnapshot = onchainTable('price_snapshot', t => ({
id: t.text().primaryKey(),
chainId: t.bigint().notNull(),
pTokenId: t.text().notNull(),
timestamp: t.bigint().notNull(),
price: t.bigint().notNull(),
}));

export const aprSnapshot = onchainTable('apr_snapshot', t => ({
id: t.text().primaryKey(),
chainId: t.bigint().notNull(),
pTokenId: t.text().notNull(),
timestamp: t.bigint().notNull(),
borrowRatePerSecond: t.bigint().notNull(),
supplyRatePerSecond: t.bigint().notNull(),
}));

0 comments on commit 119bd52

Please sign in to comment.