V40-V43: band umur vote (BARU/VALID/KADALUARSA, scan simpan semua umur) → REVOTE = VALID langsung (V42) → tag mint 1-hari + badge VOTE ULANG SEGERA (V43) ; klaim recovery jendela lewat + parse respons dict rows (B7/B8) ; backend mysql test_mariadb ; oracle test_dashboard/distribute/get_voters/mariadb ; images web/scan/dist/claim rebuild + push

This commit is contained in:
proitlab committed 2026-08-07 12:07:34 +07:00
1 parent af9a0291b9
commit 81ec6bdfe7
17 files changed
+914 -148

No files matched your search

+27 -4
View File
@@ -13,7 +13,7 @@ terkirim ganda (V22). `--dry-run` menampilkan rencana tanpa tanda tangan
import sys
import time
from datetime import datetime
from datetime import datetime, timedelta, timezone
from decimal import Decimal, ROUND_FLOOR, InvalidOperation
import requests
@@ -22,11 +22,25 @@ import db
import telegram
from config import (API_NODE, BP_PRIVATE_KEY, DATABISNIS_API,
DISTRIBUTE_ENABLED, DISTRIBUTE_MAX_ATTEMPTS, TARGET_BP,
TOKEN_CONTRACT, VEX_SYMBOL)
TOKEN_CONTRACT, VEX_MATURITY_DAYS, VEX_STALE_DAYS,
VEX_SYMBOL)
VEX_PREC = Decimal('0.0001')
def _eligible_cutoffs():
"""V40/V42: jendela reward = vote matang s/d segar: `now − STALE < last_vote ≤
now − MATURITY` (UTC-naive, konsisten dgn stempel `last_vote` dari scan).
Pemilih baru (< VEX_MATURITY_DAYS) & basi (> VEX_STALE_DAYS) ⊥ dibayar.
V42: pemilih yang SUDAH PERNAH terlihat (REVOTE, `first_seen ≤ now −
MATURITY`) dianggap VALID langsung — ⊥ tunggu masa matang; hanya pemilih
baru (first_seen tak ada / < MATURITY lalu) yang harus matang dulu."""
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):
@@ -129,9 +143,18 @@ def run_distribution(dry_run=False):
print('Distribusi dinonaktifkan (DISTRIBUTE_ENABLED=false) — no-op.',
flush=True)
return 0
voters = db.query('SELECT owner, staked FROM voters')
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 (v.last_vote <= %s '
' OR (fs.first_seen_at IS NOT NULL '
' AND fs.first_seen_at <= %s))',
[stale_cutoff, mature_cutoff, mature_cutoff])
if not voters:
print('Tidak ada pemilih segar tersimpan — no-op.', flush=True)
print('Tidak ada pemilih matang & segar tersimpan — no-op.', flush=True)
return 0
balance = fetch_balance()
if balance is None or balance < VEX_PREC: