anonpenguin23 655bd92178 Squashed 'website/' content from commit d19b985
git-subtree-dir: website
git-subtree-split: d19b98589ec5d235560a210b26195b653a65a808
2026-03-26 18:14:59 +02:00

130 lines
3.9 KiB
Go

package handler
import (
"database/sql"
"fmt"
"math"
"net/http"
"github.com/debros/orama-website/invest-api/auth"
dbpkg "github.com/debros/orama-website/invest-api/db"
"github.com/debros/orama-website/invest-api/helius"
)
func AnchatBalanceHandler(database *sql.DB, heliusClient *helius.Client) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
wallet, chain, ok := auth.WalletFromContext(r.Context())
if !ok {
jsonError(w, http.StatusUnauthorized, "wallet required")
return
}
if chain != "sol" {
jsonError(w, http.StatusBadRequest, "$ANCHAT is a Solana token — connect with a Solana wallet")
return
}
// Check current claim status
var status string
err := database.QueryRow("SELECT status FROM anchat_claims WHERE wallet = ?", wallet).Scan(&status)
hasActiveClaim := err == nil && status == "active"
hasRevokedClaim := err == nil && status == "revoked"
balance, err := heliusClient.GetTokenBalance(wallet, dbpkg.AnchatMint)
if err != nil {
jsonError(w, http.StatusInternalServerError, fmt.Sprintf("failed to check $ANCHAT balance: %v", err))
return
}
claimable := 0.0
canClaim := false
if balance >= dbpkg.AnchatMinBalance && !hasActiveClaim {
claimable = math.Floor(balance * dbpkg.AnchatClaimRate)
canClaim = true
}
jsonResponse(w, http.StatusOK, map[string]any{
"balance": balance,
"claimable_orama": claimable,
"already_claimed": hasActiveClaim,
"was_revoked": hasRevokedClaim,
"can_claim": canClaim,
"min_balance": dbpkg.AnchatMinBalance,
})
}
}
func AnchatClaimHandler(database *sql.DB, heliusClient *helius.Client) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
wallet, chain, ok := auth.WalletFromContext(r.Context())
if !ok {
jsonError(w, http.StatusUnauthorized, "wallet required")
return
}
if chain != "sol" {
jsonError(w, http.StatusBadRequest, "$ANCHAT is a Solana token — connect with a Solana wallet")
return
}
// Check if there's an active claim already
var status string
err := database.QueryRow("SELECT status FROM anchat_claims WHERE wallet = ?", wallet).Scan(&status)
if err == nil && status == "active" {
jsonError(w, http.StatusConflict, "you already have an active $ORAMA claim")
return
}
// Fresh balance (bypass cache)
balance, err := heliusClient.GetTokenBalanceFresh(wallet, dbpkg.AnchatMint)
if err != nil {
jsonError(w, http.StatusInternalServerError, fmt.Sprintf("failed to verify $ANCHAT balance: %v", err))
return
}
if balance < dbpkg.AnchatMinBalance {
jsonError(w, http.StatusBadRequest,
fmt.Sprintf("minimum %s $ANCHAT required (you have %.0f)",
formatInt(dbpkg.AnchatMinBalance), balance))
return
}
oramaAmount := math.Floor(balance * dbpkg.AnchatClaimRate)
if oramaAmount <= 0 {
jsonError(w, http.StatusBadRequest, "$ANCHAT balance too low to claim $ORAMA")
return
}
// Upsert: if previously revoked, update to active; otherwise insert
_, err = database.Exec(`
INSERT INTO anchat_claims (wallet, anchat_balance_at_claim, orama_amount, status, flagged_at, warned_at, revoked_at)
VALUES (?, ?, ?, 'active', NULL, NULL, NULL)
ON CONFLICT(wallet) DO UPDATE SET
anchat_balance_at_claim = ?,
orama_amount = ?,
status = 'active',
flagged_at = NULL,
warned_at = NULL,
revoked_at = NULL,
claimed_at = CURRENT_TIMESTAMP
`, wallet, balance, oramaAmount, balance, oramaAmount)
if err != nil {
jsonError(w, http.StatusInternalServerError, "failed to record claim")
return
}
logActivity(database, "anchat_claim", wallet, fmt.Sprintf("%.0f $ANCHAT → %.0f $ORAMA", balance, oramaAmount))
jsonResponse(w, http.StatusCreated, map[string]any{
"orama_amount": oramaAmount,
})
}
}
func formatInt(n float64) string {
if n >= 1000 {
return fmt.Sprintf("%.0fK", n/1000)
}
return fmt.Sprintf("%.0f", n)
}