min stake from backend (#78)

resolves #74

Co-authored-by: johba <johba@harb.eth>
Reviewed-on: https://codeberg.org/johba/harb/pulls/78
This commit is contained in:
johba 2025-10-11 15:30:08 +02:00
parent 0b3545091f
commit bd475c2271
11 changed files with 1176 additions and 1977 deletions

View file

@ -30,6 +30,7 @@ type stats {
stakeTotalSupply: BigInt!
outstandingStake: BigInt!
positionsUpdatedAt: BigInt!
minStake: BigInt!
totalMinted: BigInt!
totalBurned: BigInt!
totalTaxPaid: BigInt!
@ -102,6 +103,14 @@ input statsFilter {
positionsUpdatedAt_lt: BigInt
positionsUpdatedAt_gte: BigInt
positionsUpdatedAt_lte: BigInt
minStake: BigInt
minStake_not: BigInt
minStake_in: [BigInt]
minStake_not_in: [BigInt]
minStake_gt: BigInt
minStake_lt: BigInt
minStake_gte: BigInt
minStake_lte: BigInt
totalMinted: BigInt
totalMinted_not: BigInt
totalMinted_in: [BigInt]
@ -419,4 +428,4 @@ input positionsFilter {
payout_lt: BigInt
payout_gte: BigInt
payout_lte: BigInt
}
}

View file

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

View file

@ -132,7 +132,7 @@ export async function ensureStatsExists(context: StatsContext, timestamp?: bigin
}
};
const [kraikenTotalSupply, stakeTotalSupply, outstandingStake] = await Promise.all([
const [kraikenTotalSupply, stakeTotalSupply, outstandingStake, minStake] = await Promise.all([
readWithFallback(
() =>
client.readContract({
@ -163,6 +163,16 @@ export async function ensureStatsExists(context: StatsContext, timestamp?: bigin
0n,
'Stake.outstandingStake'
),
readWithFallback(
() =>
client.readContract({
abi: contracts.Kraiken.abi,
address: contracts.Kraiken.address,
functionName: 'minStake',
}),
0n,
'Kraiken.minStake'
),
]);
cachedStakeTotalSupply = stakeTotalSupply;
@ -178,6 +188,7 @@ export async function ensureStatsExists(context: StatsContext, timestamp?: bigin
ringBufferPointer: 0,
lastHourlyUpdateTimestamp: currentHour,
ringBuffer: serializeRingBuffer(makeEmptyRingBuffer()),
minStake,
});
statsData = await context.db.find(stats, { id: STATS_ID });
@ -295,3 +306,33 @@ export async function refreshOutstandingStake(context: StatsContext) {
outstandingStake,
});
}
export async function refreshMinStake(context: StatsContext, statsData?: Awaited<ReturnType<typeof ensureStatsExists>>) {
let currentStats = statsData;
if (!currentStats) {
currentStats = await context.db.find(stats, { id: STATS_ID });
}
if (!currentStats) {
currentStats = await ensureStatsExists(context);
}
if (!currentStats) return;
let minStake: bigint;
try {
minStake = await context.client.readContract({
abi: context.contracts.Kraiken.abi,
address: context.contracts.Kraiken.address,
functionName: 'minStake',
});
} catch (error) {
const logger = context.logger || console;
logger.warn('[stats.refreshMinStake] Failed to read Kraiken.minStake', error);
return;
}
if ((currentStats.minStake ?? 0n) === minStake) return;
await context.db.update(stats, { id: STATS_ID }).set({
minStake,
});
}

View file

@ -4,11 +4,13 @@ import type { Context } from 'ponder:registry';
/**
* Validates that the deployed Kraiken contract version is compatible
* with this indexer's kraiken-lib version.
*
*
* MUST be called at Ponder startup before processing any events.
* Fails hard (process.exit) on mismatch to prevent indexing wrong data.
*/
export async function validateContractVersion(context: Context): Promise<void> {
const logger = context.logger || console;
try {
const contractVersion = await context.client.readContract({
address: context.contracts.Kraiken.address,
@ -19,14 +21,14 @@ export async function validateContractVersion(context: Context): Promise<void> {
const versionNumber = Number(contractVersion);
if (!isCompatibleVersion(versionNumber)) {
console.error(getVersionMismatchError(versionNumber, 'ponder'));
logger.error(getVersionMismatchError(versionNumber, 'ponder'));
process.exit(1);
}
console.log(`✓ Contract version validated: v${versionNumber} (kraiken-lib v${KRAIKEN_LIB_VERSION})`);
logger.info(`✓ Contract version validated: v${versionNumber} (kraiken-lib v${KRAIKEN_LIB_VERSION})`);
} catch (error) {
console.error('Failed to read contract VERSION:', error);
console.error('Ensure Kraiken contract has VERSION constant and is deployed correctly');
logger.error('Failed to read contract VERSION:', error);
logger.error('Ensure Kraiken contract has VERSION constant and is deployed correctly');
process.exit(1);
}
}

View file

@ -7,6 +7,7 @@ import {
updateHourlyData,
checkBlockHistorySufficient,
RING_BUFFER_SEGMENTS,
refreshMinStake,
} from './helpers/stats';
import { validateContractVersion } from './helpers/version';
@ -80,7 +81,9 @@ ponder.on('Kraiken:Transfer', async ({ event, context }) => {
});
ponder.on('StatsBlock:block', async ({ event, context }) => {
await ensureStatsExists(context, event.block.timestamp);
const statsData = await ensureStatsExists(context, event.block.timestamp);
await refreshMinStake(context, statsData);
// Only update hourly data if we have sufficient block history
if (checkBlockHistorySufficient(context, event)) {