apps/keeper/src/jobs/sweep.ts

Moves platform income to the treasury. Shown whole, as it was in the repository when this site was built. Line numbers link: add #L12 to the address.

apps/keeper/src/jobs/sweep.ts66 lines
1// sweep: move the platform slice (Σ coins.platform_lamports − Σ sweeps) from the vault to the treasury2// (NEXT_PUBLIC_SOLARY_TREASURY, cold) once it reaches sweep.min_lamports (0.05 SOL). Never touches what the vault3// owes holders or the buyback, and keeps vault.reserve_lamports for fees. The treasury may not exist on-chain yet:4// the first transfer to it must reach the rent-exempt minimum, which the threshold covers.5// Intents (kind 'sweep'); the sweeps row is written when the transfer confirms.6import { eq } from 'drizzle-orm';7import { intents, sweeps } from '@solary/db';8import { RENT_EXEMPT_WALLET } from '@solary/core';9import { event, sol, type JobCtx, type Stats } from '../ctx';10import { createIntent, holdReason, intentState, openIntents, setIntent } from '../intents';11import { words } from '../ledger/words';12import { settingBig, vaultObligations } from './common';13 14const KIND = 'sweep';15 16async function recordSweep(ctx: JobCtx, intentId: number, sig: string, lamports: bigint): Promise<void> {17  const inserted = await ctx.db.transaction(async (t) => {18    const [seen] = await t.select({ id: sweeps.id }).from(sweeps).where(eq(sweeps.tx, sig)).limit(1);19    await t.update(intents).set({ status: 'confirmed', updatedAt: new Date() }).where(eq(intents.id, intentId));20    if (seen) return false;21    await t.insert(sweeps).values({ lamports, tx: sig });22    return true;23  });24  if (inserted) await event(ctx.db, { action: 'sweep', message: words.swept(lamports), amounts: { lamports: lamports.toString() }, sig });25}26 27export async function sweepJob(ctx: JobCtx): Promise<Stats> {28  let reconciled = 0;29  for (const i of await openIntents(ctx, KIND)) {30    const st = await intentState(ctx, i);31    if (st === 'confirmed') {32      await recordSweep(ctx, i.id, i.sig, BigInt(String(i.payload.lamports ?? '0')));33      reconciled++;34    } else if (st !== 'unknown') await setIntent(ctx, i.id, st);35  }36 37  const treasury = ctx.sol.mode === 'fake' ? (ctx.env.treasury ?? 'FAKETreasury1111111111111111111111111111111') : ctx.env.treasury;38  if (!treasury) return { reconciled, skipped: 'NEXT_PUBLIC_SOLARY_TREASURY not set' };39  const min = await settingBig(ctx, 'sweep.min_lamports', 50_000_000n);40  const reserve = await settingBig(ctx, 'vault.reserve_lamports', 10_000_000n);41  const owed = await vaultObligations(ctx);42  if (owed.platform < min) return { reconciled, platform_lamports: owed.platform.toString(), skipped: 'under the sweep minimum' };43  const balance = await ctx.sol.vaultBalance();44  const free = balance - owed.holders - owed.buyback - reserve;45  const amount = owed.platform < free ? owed.platform : free;46  if (amount < min) return { reconciled, platform_lamports: owed.platform.toString(), vault_lamports: balance.toString(), skipped: 'vault holds too little above what it owes' };47  const exists = (await ctx.sol.walletsExist([treasury])).has(treasury);48  if (!exists && amount < BigInt(RENT_EXEMPT_WALLET)) return { reconciled, skipped: 'treasury does not exist yet and the amount is under rent' };49 50  const priority = await settingBig(ctx, 'tx.priority_micro_lamports', 50_000n);51  const prepared = await ctx.sol.prepareSweep(treasury, amount, priority);52  if (!prepared.ok) return { reconciled, failed: prepared.error ?? 'simulation failed' };53  const hold = holdReason(ctx);54  if (hold) {55    ctx.log(`${hold}: would sweep ${sol(amount)} to the treasury`);56    return { reconciled, would_sweep: amount.toString() };57  }58  const intentId = await createIntent(ctx, KIND, { to: treasury, lamports: amount });59  const res = await ctx.sol.send(prepared, (sig, lvbh) => setIntent(ctx, intentId, 'sent', { sig, payload: { lastValidBlockHeight: lvbh } }));60  if (res.status === 'confirmed') {61    await recordSweep(ctx, intentId, res.signature, amount);62    return { reconciled, swept: amount.toString() };63  }64  if (res.status !== 'pending') await setIntent(ctx, intentId, res.status, { payload: { error: res.error } });65  return { reconciled, status: res.status };66}