first commit

Made-with: Cursor
This commit is contained in:
Michaël
2026-02-26 18:33:00 -03:00
commit 3734365463
76 changed files with 14133 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
import { randomInt } from "crypto";
import { v4 as uuidv4 } from "uuid";
import { config } from "../config.js";
import { getDb } from "../db/index.js";
import { getWalletBalanceSats } from "./lnbits.js";
const QUOTE_TTL_SECONDS = 60;
interface PayoutBucket {
sats: number;
weight: number;
}
function getPayoutBuckets(): PayoutBucket[] {
return [
{ sats: config.payoutSmallSats, weight: config.payoutWeightSmall },
{ sats: config.payoutMediumSats, weight: config.payoutWeightMedium },
{ sats: config.payoutLargeSats, weight: config.payoutWeightLarge },
{ sats: config.payoutJackpotSats, weight: config.payoutWeightJackpot },
];
}
/**
* Weighted random selection. Returns sats amount.
*/
export function selectWeightedPayout(): number {
const buckets = getPayoutBuckets();
const totalWeight = buckets.reduce((s, b) => s + b.weight, 0);
let r = randomInt(0, totalWeight);
for (const b of buckets) {
if (r < b.weight) return b.sats;
r -= b.weight;
}
return config.payoutSmallSats;
}
/**
* Compute payout for this claim: weighted selection, capped by daily budget remaining.
*/
export function computePayoutForClaim(todayPaidSats: number): number {
const remaining = Math.max(0, config.dailyBudgetSats - todayPaidSats);
if (remaining < config.faucetMinSats) return 0;
const selected = selectWeightedPayout();
return Math.min(selected, remaining, config.faucetMaxSats);
}
export interface CreateQuoteResult {
quoteId: string;
payoutSats: number;
expiresAt: number;
}
export async function createQuote(pubkey: string, lightningAddress: string): Promise<CreateQuoteResult | null> {
const db = getDb();
const now = Math.floor(Date.now() / 1000);
const dayStart = now - (now % 86400);
const todayPaid = await db.getPaidSatsSince(dayStart);
let payout = computePayoutForClaim(todayPaid);
if (payout <= 0) return null;
const walletBalance = await getWalletBalanceSats();
payout = Math.min(payout, Math.max(0, walletBalance));
if (payout < config.faucetMinSats) return null;
const quoteId = uuidv4();
const expiresAt = now + QUOTE_TTL_SECONDS;
await db.createQuote(quoteId, pubkey, payout, lightningAddress, expiresAt);
return { quoteId, payoutSats: payout, expiresAt };
}