From e335a8d5bf1a0a80b197a7ac15c4120a8a2cd874 Mon Sep 17 00:00:00 2001 From: Lars Gebhardt-Kusche Date: Tue, 5 May 2026 23:20:29 +0200 Subject: [PATCH] xycyxc --- modules/mining-checker/assets/css/app.css | 74 ----------------------- modules/mining-checker/assets/js/app.js | 70 --------------------- modules/mining-checker/docs/README.md | 12 +--- modules/mining-checker/pages/index.php | 12 ---- modules/mining-checker/src/Api/Router.php | 57 ++--------------- 5 files changed, 7 insertions(+), 218 deletions(-) diff --git a/modules/mining-checker/assets/css/app.css b/modules/mining-checker/assets/css/app.css index 1a9d032..01127b1 100644 --- a/modules/mining-checker/assets/css/app.css +++ b/modules/mining-checker/assets/css/app.css @@ -344,24 +344,6 @@ background: rgba(255, 255, 255, 0.05); } -#mining-checker-app .mc-token-list, -#mining-checker-app .mc-suggestion-list { - display: flex; - flex-wrap: wrap; - gap: 10px; -} - -#mining-checker-app .mc-token-list--inline { - flex: 1 1 auto; -} - -#mining-checker-app .mc-currency-selection-row { - display: flex; - flex-wrap: wrap; - gap: 16px; - align-items: flex-start; -} - #mining-checker-app .mc-inline-fields { display: flex; flex-wrap: wrap; @@ -373,59 +355,6 @@ flex: 1 1 280px; } -#mining-checker-app .mc-currency-search { - flex: 0 1 360px; - min-width: 260px; -} - -#mining-checker-app .mc-token, -#mining-checker-app .mc-suggestion { - display: inline-flex; - align-items: center; - gap: 10px; - border: 1px solid var(--mc-line); - border-radius: 999px; - padding: 10px 14px; - background: rgba(255, 255, 255, 0.06); - color: var(--mc-text); -} - -#mining-checker-app .mc-token { - cursor: pointer; -} - -#mining-checker-app .mc-token:hover, -#mining-checker-app .mc-suggestion:hover { - border-color: rgba(125, 211, 252, 0.4); - background: rgba(61, 217, 196, 0.12); -} - -#mining-checker-app .mc-token-close { - color: var(--mc-accent-strong); - font-weight: 700; - text-transform: uppercase; -} - -#mining-checker-app .mc-suggestion { - cursor: pointer; -} - -@media (max-width: 860px) { - #mining-checker-app .mc-currency-selection-row { - flex-direction: column; - } - - #mining-checker-app .mc-currency-search { - flex: 1 1 auto; - width: 100%; - min-width: 0; - } -} - -#mining-checker-app .mc-suggestion strong { - color: #ffffff; -} - #mining-checker-app .mc-alert--error { border-color: rgba(251, 113, 133, 0.28); background: rgba(127, 29, 29, 0.35); @@ -760,7 +689,6 @@ } #mining-checker-app .mc-inline-fields, - #mining-checker-app .mc-currency-selection-row, #mining-checker-app .mc-debug-tools, #mining-checker-app .mc-debug-view-switch { gap: 8px; @@ -771,8 +699,6 @@ min-width: 0; } - #mining-checker-app .mc-token, - #mining-checker-app .mc-suggestion, #mining-checker-app .mc-badge { padding: 7px 10px; font-size: 0.78rem; diff --git a/modules/mining-checker/assets/js/app.js b/modules/mining-checker/assets/js/app.js index 40f3852..06a61e9 100644 --- a/modules/mining-checker/assets/js/app.js +++ b/modules/mining-checker/assets/js/app.js @@ -8,10 +8,6 @@ const { useEffect, useMemo, useState } = React; const apiBase = root.dataset.apiBase || '/api/mining-checker/v1'; const initialProjectKey = root.dataset.defaultProjectKey || 'doge-main'; - const fxProvider = root.dataset.fxProvider || 'currencyapi'; - const fxBaseUrl = root.dataset.fxUrl || 'https://currencyapi.net'; - const fxCurrenciesUrl = root.dataset.fxCurrenciesUrl || fxBaseUrl; - const fxApiKeyMask = root.dataset.fxApiKeyMask || ''; const initialActiveTab = String(root.dataset.activeView || 'overview').trim() || 'overview'; const configuredSections = (() => { try { @@ -109,21 +105,6 @@ }); } - function buildExternalFxUrl(base) { - if (fxProvider === 'currencyapi') { - const params = new URLSearchParams({ - base: String(base || 'USD').toUpperCase(), - output: 'json', - }); - if (fxApiKeyMask) { - params.set('key', fxApiKeyMask); - } - return `${fxBaseUrl}/api/v2/rates?${params.toString()}`; - } - - return `${fxBaseUrl}/latest?base=${encodeURIComponent(String(base || 'USD').toUpperCase())}`; - } - async function loadLatestDebugTrace() { try { const response = await fetch(`${apiBase}/debug/latest`, { @@ -297,7 +278,6 @@ daily_cost_currency: 'EUR', report_currency: 'EUR', crypto_currency: 'DOGE', - fx_max_age_hours: 3, preferred_currencies: ['DOGE', 'USD', 'EUR'], cost_plans: [], currencies: [], @@ -646,7 +626,6 @@ baseline_coins_total: '', report_currency: 'EUR', crypto_currency: 'DOGE', - fx_max_age_hours: 3, }); const [moduleAuthForm, setModuleAuthForm] = useState({ required: true, @@ -1097,7 +1076,6 @@ baseline_coins_total: normalized.settings.baseline_coins_total || '', report_currency: normalized.settings.report_currency || 'EUR', crypto_currency: normalized.settings.crypto_currency || 'DOGE', - fx_max_age_hours: normalized.settings.fx_max_age_hours || 3, }); setFxSelection(Array.isArray(normalized.settings.preferred_currencies) && normalized.settings.preferred_currencies.length ? normalized.settings.preferred_currencies @@ -1372,7 +1350,6 @@ daily_cost_currency: currentSettings.daily_cost_currency, report_currency: settingsForm.report_currency || 'EUR', crypto_currency: settingsForm.crypto_currency || 'DOGE', - fx_max_age_hours: settingsForm.fx_max_age_hours || 3, preferred_currencies: Array.isArray(currentSettings.preferred_currencies) ? currentSettings.preferred_currencies : fxSelection, @@ -1788,52 +1765,6 @@ } } - async function refreshSelectedFxRates() { - setSaving(true); - setError(''); - setMessage(''); - try { - emitDebug({ - type: 'external:request-plan', - label: 'Ich rufe jetzt extern FX-Rates auf', - provider: fxProvider, - url: buildExternalFxUrl('USD'), - method: 'GET', - headers: { Accept: 'application/json' }, - }); - const probe = await request(`${apiBase}/projects/${encodeURIComponent(projectKey)}/fx-probe`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ base: 'USD' }), - timeoutMs: 20000, - }); - emitDebug({ - type: 'external:response', - label: 'Hey, hier ist der Response vor dem DB-Schritt', - url: probe.url, - http_status: probe.http_status, - curl_error: probe.curl_error, - response_headers: probe.response_headers, - response_body: probe.response_body, - }); - const result = await request(`${apiBase}/projects/${encodeURIComponent(projectKey)}/fx-refresh`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - base: 'USD', - }), - timeoutMs: 15000, - }); - await loadFxHistory(projectKey); - await loadBootstrap(projectKey); - setMessage(`Wechselkurse aktualisiert. ${result.updated_count || 0} Datensaetze gespeichert.`); - } catch (err) { - setError(err.message); - } finally { - setSaving(false); - } - } - async function copyDebugConsole() { const content = debugEntries .slice() @@ -2794,7 +2725,6 @@ inputField('Baseline Coins', 'number', settingsForm.baseline_coins_total, (value) => setSettingsForm({ ...settingsForm, baseline_coins_total: value }), '0.000001'), selectField('Standard-FIAT-Währung', settingsForm.report_currency || 'EUR', selectableFiatCurrencies.map((currency) => currency.code), (value) => setSettingsForm({ ...settingsForm, report_currency: value })), selectField('Standard-Krypto-Währung', settingsForm.crypto_currency || 'DOGE', selectableCryptoCurrencies.map((currency) => currency.code), (value) => setSettingsForm({ ...settingsForm, crypto_currency: value })), - inputField('FX maximal in Stunden wiederverwenden', 'number', String(settingsForm.fx_max_age_hours || 3), (value) => setSettingsForm({ ...settingsForm, fx_max_age_hours: value }), '0.25'), h('button', { type: 'submit', className: 'mc-button mc-button--primary', diff --git a/modules/mining-checker/docs/README.md b/modules/mining-checker/docs/README.md index e6f4680..89af70a 100644 --- a/modules/mining-checker/docs/README.md +++ b/modules/mining-checker/docs/README.md @@ -48,7 +48,6 @@ modules/mining-checker/ - `POST /api/mining-checker/v1/projects/{projectKey}/initialize` - `POST /api/mining-checker/v1/projects/{projectKey}/upgrade` - `GET /api/mining-checker/v1/projects/{projectKey}/connection-test` -- `POST /api/mining-checker/v1/projects/{projectKey}/fx-refresh` - `GET /api/mining-checker/v1/projects/{projectKey}/fx-history` - `POST /api/mining-checker/v1/projects/{projectKey}/legacy-fx-migrate` @@ -89,17 +88,8 @@ Laut OCR.space-Doku wird `POST https://api.ocr.space/parse/image` mit `file`, He ## Wechselkurse und Waehrungen -Der Endpunkt `POST /api/mining-checker/v1/projects/{projectKey}/fx-refresh` delegiert den Abruf an das Modul `fx-rates`. Der Mining-Checker speichert dabei keine eigenen FX-Snapshots mehr, sondern referenziert die `fetch_id` aus `fx-rates`. +Der Mining-Checker speichert keine eigenen FX-Snapshots mehr, sondern referenziert die `fetch_id` aus `fx-rates`. Auch der Waehrungskatalog und die bevorzugten Waehrungen kommen ausschliesslich aus `fx-rates`. Der Mining-Checker fuehrt keine eigene Waehrungstabelle und keine eigene Alias-Verwaltung mehr im Laufzeitpfad. - -Empfohlene Umgebungsvariablen: - -- `MINING_CHECKER_FX_PROVIDER=currencyapi` -- `MINING_CHECKER_FX_URL=https://currencyapi.net` -- `MINING_CHECKER_FX_CURRENCIES_URL=https://currencyapi.net` -- `MINING_CHECKER_FX_API_KEY=...` -- `MINING_CHECKER_FX_TIMEOUT=10` -- `MINING_CHECKER_FX_CACHE_TTL=21600` - `MINING_CHECKER_FX_AUTO_FETCH_ON_MISS=false` Optionaler JSON-Body: diff --git a/modules/mining-checker/pages/index.php b/modules/mining-checker/pages/index.php index cc6286e..d3ff010 100644 --- a/modules/mining-checker/pages/index.php +++ b/modules/mining-checker/pages/index.php @@ -6,14 +6,6 @@ require_once dirname(__DIR__) . '/bootstrap.php'; $moduleConfig = require dirname(__DIR__) . '/config/module.php'; $design = module_design('mining-checker'); $defaultProjectKey = (string) ($moduleConfig['default_project_key'] ?? 'doge-main'); -$fxConfig = (array) ($moduleConfig['fx'] ?? []); -$fxProvider = (string) ($fxConfig['provider'] ?? 'currencyapi'); -$fxBaseUrl = rtrim((string) ($fxConfig['url'] ?? 'https://currencyapi.net'), '/'); -$fxCurrenciesUrl = rtrim((string) ($fxConfig['currencies_url'] ?? $fxBaseUrl), '/'); -$fxApiKey = (string) ($fxConfig['api_key'] ?? ''); -$fxApiKeyMasked = $fxApiKey === '' - ? '' - : (strlen($fxApiKey) <= 10 ? $fxApiKey : substr($fxApiKey, 0, 6) . '...' . substr($fxApiKey, -4)); $sections = is_array($design['sections'] ?? null) ? $design['sections'] : []; $activeView = trim((string) ($_GET['view'] ?? 'overview')); $allowedViews = []; @@ -57,10 +49,6 @@ $moduleJs = str_replace('', '<\/script>', $moduleJs);
diff --git a/modules/mining-checker/src/Api/Router.php b/modules/mining-checker/src/Api/Router.php index 3d8502c..6988913 100644 --- a/modules/mining-checker/src/Api/Router.php +++ b/modules/mining-checker/src/Api/Router.php @@ -23,6 +23,7 @@ final class Router private const BOOTSTRAP_SNAPSHOT_LIMIT = 40; private const LONG_REQUEST_BUDGET_SECONDS = 8.0; private const OVERVIEW_WINDOW_DAYS = 15; + private const FX_FETCH_MAX_AGE_HOURS = 3.0; private string $moduleBasePath; private ModuleConfig $config; @@ -143,14 +144,6 @@ final class Router $this->respond(['data' => $this->connectionStatus()]); } - if ($resource === 'fx-refresh' && $method === 'POST') { - $this->respond(['data' => $this->refreshFxRates(Http::input())], 201); - } - - if ($resource === 'fx-probe' && $method === 'POST') { - $this->respond(['data' => $this->probeFxRates(Http::input())], 200); - } - if ($resource === 'fx-history' && $method === 'GET') { $this->respond(['data' => $this->fxHistory()]); } @@ -332,7 +325,7 @@ final class Router 'report_currency' => 'EUR', 'crypto_currency' => 'DOGE', 'display_timezone' => 'Europe/Berlin', - 'fx_max_age_hours' => 3, + 'fx_max_age_hours' => self::FX_FETCH_MAX_AGE_HOURS, 'module_theme_mode' => 'inherit', 'module_theme_accent' => 'teal', 'preferred_currencies' => ['DOGE', 'USD', 'EUR'], @@ -525,7 +518,7 @@ final class Router 'report_currency' => $backup['settings']['report_currency'] ?? 'EUR', 'crypto_currency' => $backup['settings']['crypto_currency'] ?? 'DOGE', 'display_timezone' => $backup['settings']['display_timezone'] ?? 'Europe/Berlin', - 'fx_max_age_hours' => $backup['settings']['fx_max_age_hours'] ?? 3, + 'fx_max_age_hours' => self::FX_FETCH_MAX_AGE_HOURS, 'module_theme_mode' => $backup['settings']['module_theme_mode'] ?? 'inherit', 'module_theme_accent' => $backup['settings']['module_theme_accent'] ?? 'teal', 'preferred_currencies' => $backup['settings']['preferred_currencies'] ?? ['DOGE', 'USD', 'EUR'], @@ -725,36 +718,6 @@ final class Router } } - private function refreshFxRates(array $input): array - { - $base = strtoupper(trim((string) ($input['base'] ?? 'EUR'))); - $this->debug->add('fx.refresh.start', [ - 'base' => $base, - ]); - - try { - $result = $this->fx()->refreshLatestRates(null, $base); - $this->debug->add('fx.refresh.end', [ - 'base' => $base, - 'fetch_id' => $result['fetch']['id'] ?? null, - 'rate_count' => is_array($result['rates'] ?? null) ? count($result['rates']) : null, - ]); - return $result; - } catch (\Throwable $exception) { - $this->debug->add('fx.refresh.error', [ - 'base' => $base, - 'message' => $exception->getMessage(), - ]); - throw $exception; - } - } - - private function probeFxRates(array $input): array - { - $base = strtoupper(trim((string) ($input['base'] ?? 'EUR'))); - return $this->fx()->probeLatestRates($base); - } - private function fxHistory(): array { if (!modules()->isEnabled('fx-rates') || !modules()->hasFunction('fx-rates', 'recent_fetches')) { @@ -1170,7 +1133,6 @@ final class Router 'report_currency' => 'EUR', 'crypto_currency' => 'DOGE', 'display_timezone' => 'Europe/Berlin', - 'fx_max_age_hours' => 3, 'module_theme_mode' => 'inherit', 'module_theme_accent' => 'teal', 'preferred_currencies' => $this->preferredCurrencies(), @@ -1178,9 +1140,6 @@ final class Router if (!$this->isValidTimezone((string) ($base['display_timezone'] ?? ''))) { $base['display_timezone'] = 'Europe/Berlin'; } - if (!is_numeric($base['fx_max_age_hours'] ?? null) || (float) $base['fx_max_age_hours'] <= 0) { - $base['fx_max_age_hours'] = 3; - } if (!in_array((string) ($base['module_theme_mode'] ?? ''), ['inherit', 'custom'], true)) { $base['module_theme_mode'] = 'inherit'; } @@ -1213,7 +1172,7 @@ final class Router 'report_currency' => $this->requiredCurrency($input['report_currency'] ?? 'EUR', 'report_currency'), 'crypto_currency' => $this->requiredCurrency($input['crypto_currency'] ?? 'DOGE', 'crypto_currency'), 'display_timezone' => $displayTimezone, - 'fx_max_age_hours' => $this->requiredPositiveDecimal($input['fx_max_age_hours'] ?? 3, 'fx_max_age_hours'), + 'fx_max_age_hours' => self::FX_FETCH_MAX_AGE_HOURS, 'module_theme_mode' => $this->requiredEnum($input['module_theme_mode'] ?? 'inherit', 'module_theme_mode', ['inherit', 'custom']), 'module_theme_accent' => $this->requiredEnum($input['module_theme_accent'] ?? 'teal', 'module_theme_accent', ['teal', 'logo', 'pink', 'cyan', 'orange', 'green']), 'preferred_currencies' => $this->optionalCurrencyList($input['preferred_currencies'] ?? []), @@ -2188,11 +2147,7 @@ final class Router private function resolveMeasurementFxFetchId(string $projectKey, array $payload, bool $allowRefresh, ?float $maxAgeHoursOverride = null): ?int { $measuredAt = trim((string) ($payload['measured_at'] ?? '')); - $maxAgeHours = $maxAgeHoursOverride; - if ($maxAgeHours === null) { - $settings = $this->settings($projectKey); - $maxAgeHours = is_numeric($settings['fx_max_age_hours'] ?? null) ? (float) $settings['fx_max_age_hours'] : 3.0; - } + $maxAgeHours = $maxAgeHoursOverride ?? self::FX_FETCH_MAX_AGE_HOURS; if ($allowRefresh && $measuredAt !== '' && $this->isRecentTimestamp($measuredAt, $maxAgeHours)) { $fresh = $this->fx()->ensureFreshLatestRates($maxAgeHours, 'USD'); @@ -2225,7 +2180,7 @@ final class Router private function ensureMeasurementFxReferences(string $projectKey, array $rows, ?array $settings = null): array { - $maxAgeHours = is_numeric($settings['fx_max_age_hours'] ?? null) ? (float) $settings['fx_max_age_hours'] : 3.0; + $maxAgeHours = self::FX_FETCH_MAX_AGE_HOURS; $resolvedByTimestamp = []; $resolved = []; foreach ($rows as $row) {