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:
1 parent
ee4682da00
commit
8e80653df9
9 files changed
+172
-40
No files matched your search
+3
-27
@@ -13,7 +13,7 @@ terkirim ganda (V22). `--dry-run` menampilkan rencana tanpa tanda tangan
|
||||
|
||||
import sys
|
||||
import time
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from datetime import datetime
|
||||
from decimal import Decimal, ROUND_FLOOR, InvalidOperation
|
||||
|
||||
import requests
|
||||
@@ -22,28 +22,11 @@ import db
|
||||
import telegram
|
||||
from config import (API_NODE, BP_PRIVATE_KEY, DATABISNIS_API,
|
||||
DISTRIBUTE_ENABLED, DISTRIBUTE_MAX_ATTEMPTS, TARGET_BP,
|
||||
TOKEN_CONTRACT, VEX_MATURITY_DAYS, VEX_STALE_DAYS,
|
||||
VEX_SYMBOL)
|
||||
TOKEN_CONTRACT, VEX_SYMBOL)
|
||||
|
||||
VEX_PREC = Decimal('0.0001')
|
||||
|
||||
|
||||
def _eligible_cutoffs():
|
||||
"""V40/V52: jendela reward = `last_vote > now−STALE` (⊥ basi) DAN akun
|
||||
MATANG (`first_seen_at ≤ now−MATURITY`).
|
||||
|
||||
V52: maturity diukur dari `first_seen_at` (stempel scan presisi detik),
|
||||
BUKAN `last_vote` yang terkuantisasi pekan (stake2vote) — voter baru yang
|
||||
vote Senin–Kamis tampak 4–6 hari ⇒ lolos maturity 3-hari tanpa menunggu
|
||||
(B15). Pemilih BARU (`first_seen` NULL/`> now−MATURITY`) ⊖ dibayar; akun
|
||||
yang sudah terlihat ≥ `VEX_MATURITY_DAYS` lalu (REVOTE) dibayar langsung.
|
||||
"""
|
||||
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')
|
||||
return stale_cutoff, mature_cutoff
|
||||
|
||||
|
||||
def _post_json(url, payload, max_retries=3, timeout=30):
|
||||
"""POST JSON dengan retry (node publik flaky) — pola `get_voters`."""
|
||||
for attempt in range(max_retries):
|
||||
@@ -147,14 +130,7 @@ def run_distribution(dry_run=False):
|
||||
flush=True)
|
||||
return 0
|
||||
db.ensure_first_seen_schema()
|
||||
stale_cutoff, mature_cutoff = _eligible_cutoffs()
|
||||
voters = db.query(
|
||||
'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',
|
||||
[stale_cutoff, mature_cutoff])
|
||||
voters = db.eligible_voters()
|
||||
if not voters:
|
||||
print('Tidak ada pemilih matang & segar tersimpan — no-op.', flush=True)
|
||||
return 0
|
||||
|
||||
Reference in new issue
Block a user