position stream

This commit is contained in:
johba 2025-10-11 12:33:35 +00:00
parent 0674648044
commit 55321eff65
5 changed files with 265 additions and 85 deletions

View file

@ -29,6 +29,7 @@ type stats {
kraikenTotalSupply: BigInt!
stakeTotalSupply: BigInt!
outstandingStake: BigInt!
positionsUpdatedAt: BigInt!
totalMinted: BigInt!
totalBurned: BigInt!
totalTaxPaid: BigInt!
@ -93,6 +94,14 @@ input statsFilter {
outstandingStake_lt: BigInt
outstandingStake_gte: BigInt
outstandingStake_lte: BigInt
positionsUpdatedAt: BigInt
positionsUpdatedAt_not: BigInt
positionsUpdatedAt_in: [BigInt]
positionsUpdatedAt_not_in: [BigInt]
positionsUpdatedAt_gt: BigInt
positionsUpdatedAt_lt: BigInt
positionsUpdatedAt_gte: BigInt
positionsUpdatedAt_lte: BigInt
totalMinted: BigInt
totalMinted_not: BigInt
totalMinted_in: [BigInt]

View file

@ -19,6 +19,10 @@ export const stats = onchainTable('stats', t => ({
.bigint()
.notNull()
.$default(() => 0n),
positionsUpdatedAt: t
.bigint()
.notNull()
.$default(() => 0n),
// Totals
totalMinted: t

View file

@ -112,9 +112,7 @@ export function checkBlockHistorySufficient(context: StatsContext, event: StatsE
if (blocksSinceDeployment < MINIMUM_BLOCKS_FOR_RINGBUFFER) {
// Use console.warn as fallback if context.logger is not available (e.g., in block handlers)
const logger = context.logger || console;
logger.warn(
`Insufficient block history (only ${blocksSinceDeployment} blocks available, need ${MINIMUM_BLOCKS_FOR_RINGBUFFER})`
);
logger.warn(`Insufficient block history (only ${blocksSinceDeployment} blocks available, need ${MINIMUM_BLOCKS_FOR_RINGBUFFER})`);
return false;
}
return true;
@ -176,6 +174,7 @@ export async function ensureStatsExists(context: StatsContext, timestamp?: bigin
kraikenTotalSupply,
stakeTotalSupply,
outstandingStake,
positionsUpdatedAt: timestamp ?? 0n,
ringBufferPointer: 0,
lastHourlyUpdateTimestamp: currentHour,
ringBuffer: serializeRingBuffer(makeEmptyRingBuffer()),
@ -258,6 +257,13 @@ export async function updateHourlyData(context: StatsContext, timestamp: bigint)
}
}
export async function markPositionsUpdated(context: StatsContext, timestamp: bigint) {
await ensureStatsExists(context, timestamp);
await context.db.update(stats, { id: STATS_ID }).set({
positionsUpdatedAt: timestamp,
});
}
export async function getStakeTotalSupply(context: StatsContext): Promise<bigint> {
await ensureStatsExists(context);

View file

@ -3,6 +3,7 @@ import { positions, stats, STATS_ID, TAX_RATES } from 'ponder:schema';
import {
ensureStatsExists,
getStakeTotalSupply,
markPositionsUpdated,
parseRingBuffer,
refreshOutstandingStake,
serializeRingBuffer,
@ -55,6 +56,7 @@ ponder.on('Stake:PositionCreated', async ({ event, context }) => {
});
await refreshOutstandingStake(context);
await markPositionsUpdated(context, event.block.timestamp);
});
ponder.on('Stake:PositionRemoved', async ({ event, context }) => {
@ -76,6 +78,7 @@ ponder.on('Stake:PositionRemoved', async ({ event, context }) => {
});
await refreshOutstandingStake(context);
await markPositionsUpdated(context, event.block.timestamp);
if (checkBlockHistorySufficient(context, event)) {
await updateHourlyData(context, event.block.timestamp);
@ -101,6 +104,7 @@ ponder.on('Stake:PositionShrunk', async ({ event, context }) => {
});
await refreshOutstandingStake(context);
await markPositionsUpdated(context, event.block.timestamp);
if (checkBlockHistorySufficient(context, event)) {
await updateHourlyData(context, event.block.timestamp);
@ -154,6 +158,7 @@ ponder.on('Stake:PositionTaxPaid', async ({ event, context }) => {
}
await refreshOutstandingStake(context);
await markPositionsUpdated(context, event.block.timestamp);
});
ponder.on('Stake:PositionRateHiked', async ({ event, context }) => {
@ -163,4 +168,5 @@ ponder.on('Stake:PositionRateHiked', async ({ event, context }) => {
taxRate: TAX_RATES[taxRateIndex] || 0,
taxRateIndex,
});
await markPositionsUpdated(context, event.block.timestamp);
});