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

96 lines
2.0 KiB
Go

package handler
import (
"encoding/json"
"io"
"net/http"
"sync"
"time"
)
type PriceResponse struct {
SolUSD float64 `json:"sol_usd"`
EthUSD float64 `json:"eth_usd"`
}
var (
priceCache PriceResponse
priceCacheTime time.Time
priceMu sync.RWMutex
priceTTL = 60 * time.Second
)
func PriceHandler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
prices, err := getCachedPrices()
if err != nil {
jsonError(w, http.StatusInternalServerError, "failed to fetch prices: "+err.Error())
return
}
jsonResponse(w, http.StatusOK, prices)
}
}
func getCachedPrices() (PriceResponse, error) {
priceMu.RLock()
if time.Since(priceCacheTime) < priceTTL && priceCache.SolUSD > 0 {
cached := priceCache
priceMu.RUnlock()
return cached, nil
}
priceMu.RUnlock()
prices, err := fetchCoinGeckoPrices()
if err != nil {
return PriceResponse{}, err
}
priceMu.Lock()
priceCache = prices
priceCacheTime = time.Now()
priceMu.Unlock()
return prices, nil
}
func fetchCoinGeckoPrices() (PriceResponse, error) {
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Get("https://api.coingecko.com/api/v3/simple/price?ids=solana,ethereum&vs_currencies=usd")
if err != nil {
return PriceResponse{}, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return PriceResponse{}, err
}
var data struct {
Solana struct{ USD float64 `json:"usd"` } `json:"solana"`
Ethereum struct{ USD float64 `json:"usd"` } `json:"ethereum"`
}
if err := json.Unmarshal(body, &data); err != nil {
return PriceResponse{}, err
}
return PriceResponse{
SolUSD: data.Solana.USD,
EthUSD: data.Ethereum.USD,
}, nil
}
// GetSOLPrice returns the cached SOL price (used by purchase verification).
func GetSOLPrice() float64 {
priceMu.RLock()
defer priceMu.RUnlock()
return priceCache.SolUSD
}
// GetETHPrice returns the cached ETH price.
func GetETHPrice() float64 {
priceMu.RLock()
defer priceMu.RUnlock()
return priceCache.EthUSD
}