fix: LiveStats: remove floor price from landing, fix ETH reserve data pipeline, strip browser RPC (#196)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d398c7667d
commit
7219f1b21c
4 changed files with 64 additions and 94 deletions
|
|
@ -341,6 +341,51 @@ export async function recordEthReserveSnapshot(context: StatsContext, timestamp:
|
|||
});
|
||||
}
|
||||
|
||||
// WETH address is identical across Base mainnet, Base Sepolia, and local Anvil fork
|
||||
const WETH_ADDRESS = (process.env.WETH_ADDRESS || '0x4200000000000000000000000000000000000006') as `0x${string}`;
|
||||
|
||||
// Minimal ERC-20 ABI — only balanceOf is needed
|
||||
const erc20BalanceOfAbi = [
|
||||
{
|
||||
name: 'balanceOf',
|
||||
type: 'function',
|
||||
stateMutability: 'view',
|
||||
inputs: [{ name: 'account', type: 'address' }],
|
||||
outputs: [{ name: '', type: 'uint256' }],
|
||||
},
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Read WETH balance of the Uniswap V3 pool via Ponder's cached client and
|
||||
* persist it as `lastEthReserve` in the stats row.
|
||||
*
|
||||
* Call this from any event handler where a trade or stake changes the pool
|
||||
* balance (Kraiken:Transfer buys/sells, Stake:PositionCreated/Removed).
|
||||
* EthScarcity/EthAbundance handlers already receive the balance in event args
|
||||
* and update `lastEthReserve` directly via `updateReserveStats()`.
|
||||
*/
|
||||
export async function updateEthReserve(context: StatsContext, poolAddress: `0x${string}`) {
|
||||
let wethBalance: bigint;
|
||||
try {
|
||||
wethBalance = await context.client.readContract({
|
||||
abi: erc20BalanceOfAbi,
|
||||
address: WETH_ADDRESS,
|
||||
functionName: 'balanceOf',
|
||||
args: [poolAddress],
|
||||
});
|
||||
} catch (error) {
|
||||
const logger = getLogger(context);
|
||||
logger.warn('[stats.updateEthReserve] Failed to read WETH balance', error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (wethBalance === 0n) return; // Pool not yet seeded — don't overwrite a real value with 0
|
||||
|
||||
await context.db.update(stats, { id: STATS_ID }).set({
|
||||
lastEthReserve: wethBalance,
|
||||
});
|
||||
}
|
||||
|
||||
export async function refreshMinStake(context: StatsContext, statsData?: Awaited<ReturnType<typeof ensureStatsExists>>) {
|
||||
let currentStats = statsData;
|
||||
if (!currentStats) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
checkBlockHistorySufficient,
|
||||
RING_BUFFER_SEGMENTS,
|
||||
refreshMinStake,
|
||||
updateEthReserve,
|
||||
} from './helpers/stats';
|
||||
import { validateContractVersion } from './helpers/version';
|
||||
|
||||
|
|
@ -138,6 +139,9 @@ ponder.on('Kraiken:Transfer', async ({ event, context }) => {
|
|||
blockNumber: Number(event.block.number),
|
||||
txHash: event.transaction.hash,
|
||||
});
|
||||
|
||||
// Update ETH reserve from pool WETH balance — buys/sells shift pool ETH
|
||||
await updateEthReserve(context, POOL_ADDRESS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,13 @@ import {
|
|||
refreshOutstandingStake,
|
||||
updateHourlyData,
|
||||
checkBlockHistorySufficient,
|
||||
updateEthReserve,
|
||||
} from './helpers/stats';
|
||||
import type { StatsContext } from './helpers/stats';
|
||||
|
||||
// Pool address — staking/unstaking events keep lastEthReserve fresh alongside buy/sell events
|
||||
const POOL_ADDRESS = (process.env.POOL_ADDRESS || '0x1f69cbfc7d3529a4fb4eadf18ec5644b2603b5ab') as `0x${string}`;
|
||||
|
||||
const ZERO = 0n;
|
||||
|
||||
async function getKraikenTotalSupply(context: StatsContext) {
|
||||
|
|
@ -66,6 +70,8 @@ ponder.on('Stake:PositionCreated', async ({ event, context }) => {
|
|||
|
||||
await refreshOutstandingStake(context);
|
||||
await markPositionsUpdated(context, event.block.timestamp);
|
||||
// Keep ETH reserve fresh — stake events may coincide with pool activity
|
||||
await updateEthReserve(context, POOL_ADDRESS);
|
||||
});
|
||||
|
||||
ponder.on('Stake:PositionRemoved', async ({ event, context }) => {
|
||||
|
|
@ -100,6 +106,8 @@ ponder.on('Stake:PositionRemoved', async ({ event, context }) => {
|
|||
|
||||
await refreshOutstandingStake(context);
|
||||
await markPositionsUpdated(context, event.block.timestamp);
|
||||
// Keep ETH reserve fresh — unstake events may coincide with pool activity
|
||||
await updateEthReserve(context, POOL_ADDRESS);
|
||||
|
||||
if (checkBlockHistorySufficient(context, event)) {
|
||||
await updateHourlyData(context, event.block.timestamp);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue