fix: 2026-06-04 audit pass — README, USB pack, multi-area fixes
WS ticket dashboard auth, builder universal signing/size limits/fusion obfuscation/dropper bundles, Path Tracer WireGuard topology, SessionGate degraded mode and download timeouts, server bootstrap (data dir, cloudflared dedupe, config port precedence), agent mesh/miner/spread fixes. README refreshed; usb bundle repacked; PROBLEMS.md audit log updated.
This commit is contained in:
@@ -155,21 +155,16 @@ func (f *FleetHandler) GetXMRPrice(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
f.xmrPriceMu.Unlock()
|
||||
|
||||
client := &http.Client{Timeout: 8 * time.Second}
|
||||
resp, err := client.Get("https://api.coingecko.com/api/v3/simple/price?ids=monero&vs_currencies=usd") //nolint:gosec
|
||||
usd, err := fetchCoinGeckoXMRPrice()
|
||||
if err != nil {
|
||||
http.Error(w, "price fetch failed: "+err.Error(), http.StatusServiceUnavailable)
|
||||
status := http.StatusServiceUnavailable
|
||||
msg := err.Error()
|
||||
if strings.Contains(msg, "status") || strings.Contains(msg, "parse") {
|
||||
status = http.StatusBadGateway
|
||||
}
|
||||
http.Error(w, "price fetch failed: "+msg, status)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
|
||||
|
||||
var raw map[string]map[string]float64
|
||||
if err := json.Unmarshal(body, &raw); err != nil || raw["monero"] == nil {
|
||||
http.Error(w, "price parse failed", http.StatusBadGateway)
|
||||
return
|
||||
}
|
||||
usd := raw["monero"]["usd"]
|
||||
|
||||
entry := &xmrPriceEntry{USD: usd, fetchedAt: time.Now()}
|
||||
f.xmrPriceMu.Lock()
|
||||
@@ -183,6 +178,41 @@ func (f *FleetHandler) GetXMRPrice(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
const coingeckoXMRURL = "https://api.coingecko.com/api/v3/simple/price?ids=monero&vs_currencies=usd"
|
||||
|
||||
func fetchCoinGeckoXMRPrice() (float64, error) {
|
||||
client := &http.Client{Timeout: 8 * time.Second}
|
||||
var lastErr error
|
||||
for attempt := 0; attempt < 3; attempt++ {
|
||||
if attempt > 0 {
|
||||
time.Sleep(time.Duration(attempt) * 400 * time.Millisecond)
|
||||
}
|
||||
resp, err := client.Get(coingeckoXMRURL) //nolint:gosec
|
||||
if err != nil {
|
||||
lastErr = err
|
||||
continue
|
||||
}
|
||||
body, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode >= 500 {
|
||||
lastErr = fmt.Errorf("coingecko status %d", resp.StatusCode)
|
||||
continue
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return 0, fmt.Errorf("coingecko status %d", resp.StatusCode)
|
||||
}
|
||||
var raw map[string]map[string]float64
|
||||
if err := json.Unmarshal(body, &raw); err != nil || raw["monero"] == nil {
|
||||
return 0, fmt.Errorf("price parse failed")
|
||||
}
|
||||
return raw["monero"]["usd"], nil
|
||||
}
|
||||
if lastErr != nil {
|
||||
return 0, lastErr
|
||||
}
|
||||
return 0, fmt.Errorf("price fetch failed")
|
||||
}
|
||||
|
||||
// GetEarningsEstimate — kept for backwards compat; delegates to GetEarnings.
|
||||
func (f *FleetHandler) GetEarningsEstimate(w http.ResponseWriter, r *http.Request) {
|
||||
f.GetEarnings(w, r)
|
||||
|
||||
Reference in New Issue
Block a user