klaim baseline saldo stabil (V56/B18) + endpoint cek akun payout-eligible /api/voter (V57)

V56/B18: pre-claim liquid balance dibaca SEKALI per window (poll_claim) dan dibawa ke tiap _try_claim_once — klaim yang mendarat di attempt 1 membuat before attempt 2 (ditolak already-claimed) sudah termasuk reward → delta 0 → alert palsu KLAIM MENDARAT · REWARD TAK TERUKUR (kasus 10 Agt: bfa9ab02 reward 1679.3365 vs tx ditolak b0a8b2f9) ; oracle B18 attempt-1-mendarat → claimed + reward asli terukur

V57: db.py single source eligible_voters(owner=None) — SQL jendela payout V40/V52 (last_vote > now−STALE AND first_seen_at IS NOT NULL AND first_seen_at ≤ now−MATURITY, cutoff UTC-naive) dipakai BAIK distribute.py run_distribution (refactor, hapus _eligible_cutoffs) MAUPUN endpoint baru GET /api/voter/<owner> → 200 {owner, is_valid_voter} (DB-snapshot, selalu 200, ⊖ format-validation); BARU/kadaluarsa/hidden/asing → false ; docs §I/§V/V57 + T50 + AGENTS ; oracle test_dashboard (V57 true/false + drift endpoint==db pool + pool distribusi==db) + test_distribute (mock eligible_voters utk no-op, distribusi luas)
This commit is contained in:
proitlab committed 2026-08-12 22:28:42 +07:00
1 parent ee4682da00
commit 8e80653df9
9 files changed
+172 -40

No files matched your search

+28 -1
View File
@@ -8,7 +8,7 @@ skema `voters` yang sama; query berbagi sintaks ditulis dengan placeholder
import sqlite3
from config import (DB_BACKEND, DB_HOST, DB_NAME, DB_PASS, DB_PORT, DB_PATH,
DB_USER)
DB_USER, VEX_MATURITY_DAYS, VEX_STALE_DAYS)
# Skema voters — sama untuk kedua backend (I.db)
_COLS = (
@@ -388,6 +388,33 @@ def record_first_seen(rows, scanned_at):
conn.close()
def eligible_voters(owner=None):
"""V57: pemilih yang memenuhi syarat reward (single source, dipakai
`distribute.py` + endpoint `/api/voter/<owner>`).
Jendela reward V40/V52 = `last_vote > now−STALE` (⊥ basi) DAN akun MATANG
(`first_seen_at IS NOT NULL` DAN `first_seen_at ≤ now−MATURITY`). Maturity
diukur dari `first_seen_at` (presisi detik; B15). Tanpa `owner` → semua
baris `(owner, staked)` utk distribusi; dengan `owner` → baris akun itu
(`[]` bila tak memenuhi syarat) utk cek endpoint.
"""
from datetime import datetime, timedelta, timezone
now = datetime.now(timezone.utc).replace(tzinfo=None)
stale_cutoff = (now - timedelta(days=VEX_STALE_DAYS)).isoformat(timespec='seconds')
mature_cutoff = (now - timedelta(days=VEX_MATURITY_DAYS)).isoformat(timespec='seconds')
sql = ('SELECT v.owner, v.staked FROM voters v '
'LEFT JOIN voter_first_seen fs ON fs.owner = v.owner '
'WHERE v.last_vote > %s '
' AND fs.first_seen_at IS NOT NULL '
' AND fs.first_seen_at <= %s')
params = [stale_cutoff, mature_cutoff]
if owner is not None:
sql += ' AND v.owner = %s'
params.append(owner)
ensure_first_seen_schema()
return query(sql, params)
def pending_claim_fee():
"""Klaim terbaru dengan fee belum terkirim (fee_amount > 0) → baris | None.