From faf45e60e452741bf884a53ffcdb24c20d6a3317 Mon Sep 17 00:00:00 2001 From: DanS Date: Thu, 15 Oct 2026 10:56:36 -0500 Subject: [PATCH] fix(mining): make "Est. Daily" honest about variance and fees The mining "Est. Daily" was a solo expected-value (your hashrate share x blocks/day x a fixed block reward) rendered in the same green as the real Today / Yesterday / All-Time earnings, off an instantaneous hashrate and gross of pool fees. It read like a dependable daily income when it is a long-run statistical average with huge (Poisson) variance. Framing: - The estimate is now drawn in a neutral colour, not the green "money earned" colour (the actual mined totals stay green). - A sub-label in BOTH modes marks it as an average ("avg", or "avg, net" in pool mode when the fee is applied), replacing the pool-only "before pool fee" note. - A hover tooltip over the column explains the variance ("often nothing for long stretches, then a lump - NOT a steady daily income") and the fee status (after the N% fee / before the fee when unknown / nothing for solo and 0%-fee pools). Accuracy: - Uses a trailing-average hashrate instead of the instantaneous / 10s snapshot: pool prefers hashrate_15m (then 60s, then 10s); solo uses the mean of hashrate_history once there are >=10 samples, else the instant rate. This stops a spike or a momentary dip from swinging the figure. - Subtracts the known pool fee so pool-mode figures are net; synthetic or unmatched pools stay gross and the tooltip says the fee is unknown. The static block reward and true pool-reported earnings are intentionally out of scope (the latter needs a new pool-API field). New i18n keys are translated into all eight locales; the CJK subset font is rebuilt for the three new glyphs. Builds + test suites pass on both variants. Co-Authored-By: Claude Opus 4.8 --- res/fonts/NotoSansCJK-Subset.ttf | Bin 769504 -> 770636 bytes res/lang/de.json | 5 +++ res/lang/es.json | 5 +++ res/lang/fr.json | 5 +++ res/lang/ja.json | 5 +++ res/lang/ko.json | 5 +++ res/lang/pt.json | 5 +++ res/lang/ru.json | 5 +++ res/lang/zh.json | 5 +++ src/ui/windows/mining_earnings.cpp | 67 +++++++++++++++++++++++++---- src/util/i18n.cpp | 5 +++ 11 files changed, 103 insertions(+), 9 deletions(-) diff --git a/res/fonts/NotoSansCJK-Subset.ttf b/res/fonts/NotoSansCJK-Subset.ttf index e13e2f946a5fc5b72084c4b15321d94b5e31427d..e4e1e0110b58363a6d25e0a79556b2bb1a746390 100644 GIT binary patch delta 24677 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 V%#Ipr5PkaSP-TRe)B{?TB44`S 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 diff --git a/res/lang/de.json b/res/lang/de.json index 8cddb65..ea03e2d 100644 --- a/res/lang/de.json +++ b/res/lang/de.json @@ -1308,6 +1308,8 @@ "mining_est_block": "Gesch. Block", "mining_est_daily": "Gesch. täglich", "mining_est_daily_pool_sub": "grobe Solo-Äquivalenz, vor Pool-Gebühr", + "mining_est_daily_sub": "Ø", + "mining_est_daily_sub_net": "Ø, netto", "mining_filter_all": "Alle", "mining_filter_tip_all": "Alle Einnahmen anzeigen", "mining_filter_tip_pool": "Nur Pool-Einnahmen anzeigen", @@ -2108,6 +2110,9 @@ "tt_low_spec": "Alle aufwendigen visuellen Effekte deaktivieren\\nHotkey: Ctrl+Shift+Down", "tt_merge": "Mehrere UTXOs einer Adresse zusammenführen", "tt_mine_idle": "Mining automatisch starten, wenn das\\nSystem inaktiv ist (keine Tastatur-/Mauseingabe)", + "tt_mining_est_daily": "Ein langfristiger statistischer Durchschnitt für Ihren aktuellen Hashrate-Anteil am Netzwerk. Echte Mining-Belohnungen kommen zufällig (Poisson) – oft lange nichts, dann ein Batzen – das ist also KEIN gleichmäßiges Tageseinkommen.", + "tt_mining_est_daily_fee_fmt": "Angezeigt nach der %.1f%% Pool-Gebühr.", + "tt_mining_est_daily_nofee": "Vor Abzug der Pool-Gebühr angezeigt (Gebühr für diesen Pool unbekannt).", "tt_new_mining_address": "Erstellt eine transparente Adresse (R…) für Solo-Mining-Belohnungen. Sie kann keine Zahlungen empfangen – teilen Sie dafür eine abgeschirmte Adresse.", "tt_noise": "Körnungstextur-Intensität (0% = aus, 100% = maximum)", "tt_open_app_dir": "Den ObsidianDragon-Ordner (Einstellungen, Themes, Logs) im Dateimanager öffnen", diff --git a/res/lang/es.json b/res/lang/es.json index 4bb0fe0..eed85a7 100644 --- a/res/lang/es.json +++ b/res/lang/es.json @@ -1308,6 +1308,8 @@ "mining_est_block": "Bloque Est.", "mining_est_daily": "Diario Est.", "mining_est_daily_pool_sub": "equivalente solo aproximado, antes de la comisión del pool", + "mining_est_daily_sub": "prom.", + "mining_est_daily_sub_net": "prom., neto", "mining_filter_all": "Todos", "mining_filter_tip_all": "Mostrar todas las ganancias", "mining_filter_tip_pool": "Mostrar solo ganancias del pool", @@ -2108,6 +2110,9 @@ "tt_low_spec": "Desactivar todos los efectos visuales pesados\\nAtajo: Ctrl+Shift+Down", "tt_merge": "Consolidar múltiples UTXOs en una dirección", "tt_mine_idle": "Iniciar minería automáticamente cuando el\\nsistema esté inactivo (sin entrada de teclado/ratón)", + "tt_mining_est_daily": "Un promedio estadístico a largo plazo para tu proporción actual de hashrate en la red. Las recompensas reales de minería llegan al azar (Poisson): a menudo nada durante largos periodos y luego una suma; por eso NO es un ingreso diario constante.", + "tt_mining_est_daily_fee_fmt": "Se muestra tras la comisión del pool del %.1f%%.", + "tt_mining_est_daily_nofee": "Se muestra antes de la comisión del pool (comisión desconocida para este pool).", "tt_new_mining_address": "Crea una dirección transparente (R…) para recompensas de minería en solitario. No puede recibir pagos; para eso comparte una dirección blindada.", "tt_noise": "Intensidad de textura granulada (0% = apagado, 100% = máximo)", "tt_open_app_dir": "Abrir la carpeta de ObsidianDragon (configuración, temas, registros) en el explorador de archivos", diff --git a/res/lang/fr.json b/res/lang/fr.json index cf13c5d..d3a2cc4 100644 --- a/res/lang/fr.json +++ b/res/lang/fr.json @@ -1308,6 +1308,8 @@ "mining_est_block": "Bloc est.", "mining_est_daily": "Est. quotidien", "mining_est_daily_pool_sub": "équivalent solo approximatif, avant les frais du pool", + "mining_est_daily_sub": "moy.", + "mining_est_daily_sub_net": "moy., net", "mining_filter_all": "Tout", "mining_filter_tip_all": "Afficher tous les gains", "mining_filter_tip_pool": "Afficher uniquement les gains du pool", @@ -2108,6 +2110,9 @@ "tt_low_spec": "Désactiver tous les effets visuels lourds\\nRaccourci : Ctrl+Shift+Down", "tt_merge": "Consolider plusieurs UTXOs vers une adresse", "tt_mine_idle": "Démarrer le minage automatiquement quand le\\nsystème est inactif (aucune entrée clavier/souris)", + "tt_mining_est_daily": "Une moyenne statistique à long terme pour votre part actuelle de hashrate dans le réseau. Les récompenses réelles de minage arrivent au hasard (Poisson) — souvent rien pendant longtemps, puis une somme — ce n'est donc PAS un revenu quotidien régulier.", + "tt_mining_est_daily_fee_fmt": "Affiché après les %.1f%% de frais de pool.", + "tt_mining_est_daily_nofee": "Affiché avant les frais de pool (frais inconnus pour ce pool).", "tt_new_mining_address": "Crée une adresse transparente (R…) pour les récompenses de minage en solo. Elle ne peut pas recevoir de paiements — partagez une adresse blindée pour cela.", "tt_noise": "Intensité de texture grainée (0% = désactivé, 100% = maximum)", "tt_open_app_dir": "Ouvrir le dossier ObsidianDragon (paramètres, thèmes, journaux) dans le gestionnaire de fichiers", diff --git a/res/lang/ja.json b/res/lang/ja.json index ef1d586..fcb2d8c 100644 --- a/res/lang/ja.json +++ b/res/lang/ja.json @@ -1308,6 +1308,8 @@ "mining_est_block": "予測ブロック", "mining_est_daily": "予測日収", "mining_est_daily_pool_sub": "おおよそのソロ換算(プール手数料前)", + "mining_est_daily_sub": "平均", + "mining_est_daily_sub_net": "平均・手取り", "mining_filter_all": "すべて", "mining_filter_tip_all": "すべての収益を表示", "mining_filter_tip_pool": "プール収益のみ表示", @@ -2108,6 +2110,9 @@ "tt_low_spec": "すべての重い視覚効果を無効化\\nホットキー:Ctrl+Shift+Down", "tt_merge": "複数の UTXO を一つのアドレスに統合", "tt_mine_idle": "システムがアイドル状態(キーボード/マウス入力なし)\\nのとき自動的にマイニングを開始", + "tt_mining_est_daily": "ネットワーク全体に占める現在のハッシュレート比率に基づく長期的な統計平均です。実際のマイニング報酬はランダム(ポアソン分布)に発生し、長期間ゼロが続いた後にまとまって得られることが多いため、これは安定した日次収入ではありません。", + "tt_mining_est_daily_fee_fmt": "%.1f%% のプール手数料を差し引いた値です。", + "tt_mining_est_daily_nofee": "プール手数料を差し引く前の値です(このプールの手数料は不明)。", "tt_new_mining_address": "ソロマイニング報酬用の透明(R…)アドレスを作成します。支払いは受け取れません。支払いにはシールドアドレスを共有してください。", "tt_noise": "グレインテクスチャ強度(0% = オフ、100% = 最大)", "tt_open_app_dir": "ObsidianDragon フォルダ(設定、テーマ、ログ)をファイルマネージャーで開く", diff --git a/res/lang/ko.json b/res/lang/ko.json index f1b1fa4..58b30f1 100644 --- a/res/lang/ko.json +++ b/res/lang/ko.json @@ -1308,6 +1308,8 @@ "mining_est_block": "예상 블록", "mining_est_daily": "예상 일일 수익", "mining_est_daily_pool_sub": "대략적인 솔로 환산, 풀 수수료 전", + "mining_est_daily_sub": "평균", + "mining_est_daily_sub_net": "평균, 순", "mining_filter_all": "전체", "mining_filter_tip_all": "모든 수익 표시", "mining_filter_tip_pool": "풀 수익만 표시", @@ -2108,6 +2110,9 @@ "tt_low_spec": "모든 고부하 시각 효과 비활성화\\n단축키: Ctrl+Shift+Down", "tt_merge": "여러 UTXO를 하나의 주소로 통합", "tt_mine_idle": "시스템이 유휴 상태(키보드/마우스 입력 없음)일 때\\n자동으로 채굴 시작", + "tt_mining_est_daily": "네트워크에서 현재 해시레이트 비중에 대한 장기 통계 평균입니다. 실제 채굴 보상은 무작위(푸아송)로 도착하여 오랫동안 아무것도 없다가 한꺼번에 들어오는 경우가 많으므로, 이는 꾸준한 일일 수입이 아닙니다.", + "tt_mining_est_daily_fee_fmt": "%.1f%% 풀 수수료를 제외하고 표시됩니다.", + "tt_mining_est_daily_nofee": "풀 수수료를 제외하기 전 값입니다(이 풀의 수수료는 알 수 없음).", "tt_new_mining_address": "솔로 채굴 보상용 투명(R…) 주소를 만듭니다. 결제는 받을 수 없으니, 결제용으로는 차폐 주소를 공유하세요.", "tt_noise": "그레인 텍스처 강도 (0% = 끔, 100% = 최대)", "tt_open_app_dir": "파일 관리자에서 ObsidianDragon 폴더(설정, 테마, 로그)를 엽니다", diff --git a/res/lang/pt.json b/res/lang/pt.json index 67df707..80501e1 100644 --- a/res/lang/pt.json +++ b/res/lang/pt.json @@ -1308,6 +1308,8 @@ "mining_est_block": "Bloco Est.", "mining_est_daily": "Est. Diário", "mining_est_daily_pool_sub": "equivalente solo aproximado, antes da taxa do pool", + "mining_est_daily_sub": "méd.", + "mining_est_daily_sub_net": "méd., líq.", "mining_filter_all": "Todos", "mining_filter_tip_all": "Mostrar todos os ganhos", "mining_filter_tip_pool": "Mostrar apenas ganhos do pool", @@ -2108,6 +2110,9 @@ "tt_low_spec": "Desativar todos os efeitos visuais pesados\\nAtalho: Ctrl+Shift+Down", "tt_merge": "Consolidar múltiplos UTXOs em um endereço", "tt_mine_idle": "Iniciar mineração automaticamente quando o\\nsistema estiver ocioso (sem entrada de teclado/mouse)", + "tt_mining_est_daily": "Uma média estatística de longo prazo para a sua fração atual de hashrate na rede. As recompensas reais de mineração chegam de forma aleatória (Poisson) — muitas vezes nada por longos períodos e depois um valor — por isso NÃO é uma renda diária constante.", + "tt_mining_est_daily_fee_fmt": "Mostrado após a taxa de %.1f%% do pool.", + "tt_mining_est_daily_nofee": "Mostrado antes da taxa do pool (taxa desconhecida para este pool).", "tt_new_mining_address": "Cria um endereço transparente (R…) para recompensas de mineração solo. Ele não pode receber pagamentos — compartilhe um endereço blindado para isso.", "tt_noise": "Intensidade de textura granulada (0% = desligado, 100% = máximo)", "tt_open_app_dir": "Abrir a pasta ObsidianDragon (configurações, temas, logs) no gerenciador de arquivos", diff --git a/res/lang/ru.json b/res/lang/ru.json index cb30f28..96c7a91 100644 --- a/res/lang/ru.json +++ b/res/lang/ru.json @@ -1308,6 +1308,8 @@ "mining_est_block": "Расч. блок", "mining_est_daily": "Расч. за день", "mining_est_daily_pool_sub": "примерный соло-эквивалент, до комиссии пула", + "mining_est_daily_sub": "сред.", + "mining_est_daily_sub_net": "сред., нетто", "mining_filter_all": "Все", "mining_filter_tip_all": "Показать все доходы", "mining_filter_tip_pool": "Показать только доходы пула", @@ -2108,6 +2110,9 @@ "tt_low_spec": "Отключить все тяжёлые визуальные эффекты\\nГорячая клавиша: Ctrl+Shift+Down", "tt_merge": "Объединить несколько UTXO в один адрес", "tt_mine_idle": "Автоматически начать майнинг при\\nпростое системы (нет ввода с клавиатуры/мыши)", + "tt_mining_est_daily": "Долгосрочное статистическое среднее для вашей текущей доли хешрейта в сети. Реальные награды за майнинг приходят случайно (по Пуассону) — часто подолгу ничего, а затем сразу много, — поэтому это НЕ стабильный ежедневный доход.", + "tt_mining_est_daily_fee_fmt": "Показано за вычетом комиссии пула %.1f%%.", + "tt_mining_est_daily_nofee": "Показано до вычета комиссии пула (комиссия этого пула неизвестна).", "tt_new_mining_address": "Создаёт прозрачный адрес (R…) для наград за соло-майнинг. Он не принимает платежи — для них сообщайте экранированный адрес.", "tt_noise": "Интенсивность зернистой текстуры (0% = выкл., 100% = максимум)", "tt_open_app_dir": "Открыть папку ObsidianDragon (настройки, темы, логи) в файловом менеджере", diff --git a/res/lang/zh.json b/res/lang/zh.json index a6c7cd9..fef40fb 100644 --- a/res/lang/zh.json +++ b/res/lang/zh.json @@ -1308,6 +1308,8 @@ "mining_est_block": "预计区块", "mining_est_daily": "预计日收益", "mining_est_daily_pool_sub": "粗略的单人挖矿等值,扣除矿池费用前", + "mining_est_daily_sub": "平均", + "mining_est_daily_sub_net": "平均·净", "mining_filter_all": "全部", "mining_filter_tip_all": "显示所有收益", "mining_filter_tip_pool": "仅显示矿池收益", @@ -2108,6 +2110,9 @@ "tt_low_spec": "禁用所有重度视觉效果\\n快捷键:Ctrl+Shift+Down", "tt_merge": "将多个 UTXO 合并到一个地址", "tt_mine_idle": "系统空闲时自动开始挖矿\\n(无键盘/鼠标输入)", + "tt_mining_est_daily": "基于您当前在全网算力占比的长期统计平均值。实际挖矿奖励是随机到达的(泊松分布)——常常很长时间没有,然后一次性获得一笔,因此这并不是稳定的每日收入。", + "tt_mining_est_daily_fee_fmt": "已扣除 %.1f%% 矿池手续费。", + "tt_mining_est_daily_nofee": "未扣除矿池手续费(此矿池手续费未知)。", "tt_new_mining_address": "创建一个用于单人挖矿奖励的透明(R…)地址。它无法接收付款——收款请提供屏蔽地址。", "tt_noise": "颗粒纹理强度(0% = 关闭,100% = 最大)", "tt_open_app_dir": "在文件管理器中打开 ObsidianDragon 文件夹(设置、主题、日志)", diff --git a/src/ui/windows/mining_earnings.cpp b/src/ui/windows/mining_earnings.cpp index 186f23c..d529b73 100644 --- a/src/ui/windows/mining_earnings.cpp +++ b/src/ui/windows/mining_earnings.cpp @@ -10,6 +10,7 @@ #include "../../util/i18n.h" #include "../../util/platform.h" #include "../../config/settings.h" +#include "../../util/pool_registry.h" #include "../schema/ui_schema.h" #include "../material/type.h" #include "../material/draw_helpers.h" @@ -68,15 +69,38 @@ void RenderMiningEarnings(App* app, const WalletState& state, const MiningInfo& minedAllTimeCount = earn.allTimeCount; const std::vector& recentMined = earn.recent; - // Est. Daily = expected reward for YOUR own hashrate share of the network. In pool mode this uses - // your local miner rate (pool_mining.hashrate_10s), NOT the pool's aggregate rate: pool payouts are - // share-proportional, so your expected daily is the same solo-equivalent value (a rough estimate, - // before the pool fee). Using the pool's total rate here would show the POOL's earnings, not yours. (M-05) - double estHashrate = s_pool_mode ? state.pool_mining.hashrate_10s : mining.localHashrate; + // Est. Daily is a statistical long-run AVERAGE of your reward for your hashrate share of the + // network -- NOT a steady income. Actual rewards arrive at random (Poisson): often nothing for + // long stretches, then a lump. We feed EstimateHoursToBlock a TRAILING-AVERAGE hashrate (not an + // instantaneous / 10s snapshot) so a spike or a momentary dip doesn't swing the figure, and in + // pool mode we subtract the known pool fee so the number is net. Pool payouts are share- + // proportional, so your expected daily equals this solo-equivalent value (using the pool's + // aggregate rate would show the POOL's earnings, not yours). (M-05 / A+B) + double estHashrate; + if (s_pool_mode) { + const auto& pm = state.pool_mining; + estHashrate = pm.hashrate_15m > 0.0 ? pm.hashrate_15m + : pm.hashrate_60s > 0.0 ? pm.hashrate_60s + : pm.hashrate_10s; // 15m avg preferred; fall back as it warms up + } else { + estHashrate = mining.localHashrate; + if (mining.hashrate_history.size() >= 10) { // enough samples -> trailing mean + double sum = 0.0; + for (double h : mining.hashrate_history) sum += h; + estHashrate = sum / (double)mining.hashrate_history.size(); + } + } double est_hours_2 = EstimateHoursToBlock(estHashrate, mining.networkHashrate, mining.difficulty); double estDailyBlocks = (est_hours_2 > 0) ? (24.0 / est_hours_2) : 0.0; double blockReward = schema::UI().drawElement("business", "block-reward").size; double estDaily = estDailyBlocks * blockReward; + // Pool fee: compile-time known fee for the configured pool (<0 = unknown/synthetic pool -> gross). + double estFeePct = -1.0; + if (s_pool_mode) { + const util::KnownPool* kp = util::findKnownPoolByUrl(state.pool_mining.pool_url); + if (kp && kp->feePercent >= 0.0) estFeePct = kp->feePercent; + } + if (s_pool_mode && estFeePct > 0.0) estDaily *= (1.0 - estFeePct / 100.0); bool estActive = isMiningActive && estDaily > 0; ImU32 greenCol2 = Success(); @@ -185,15 +209,19 @@ void RenderMiningEarnings(App* app, const WalletState& state, const MiningInfo& snprintf(estVal, sizeof(estVal), "~%.4f", estDaily); else snprintf(estVal, sizeof(estVal), "%s", TR("grpc_na")); - // Disclose in pool mode that Est. Daily is a rough solo-equivalent (before the pool fee), so the - // number isn't silently mismatched to its plain "Est. Daily" label. (M-05) - const char* estSub = (s_pool_mode && estActive) ? TR("mining_est_daily_pool_sub") : nullptr; + // Flag that Est. Daily is a long-run AVERAGE in both modes (so it doesn't read as realized + // income), and whether it is net of the pool fee. Tooltip below carries the full variance note. + const char* estSub = !estActive ? nullptr + : (s_pool_mode && estFeePct > 0.0) ? TR("mining_est_daily_sub_net") + : TR("mining_est_daily_sub"); + // Neutral (not green/"income") colour for the estimate — it's a probability, not money earned. + const ImU32 estCol = estActive ? OnSurfaceMedium() : OnSurfaceDisabled(); EarningsEntry entries[] = { { TR("mining_today"), todayVal, todaySub, greenCol2 }, { TR("mining_yesterday"), yesterdayVal, yesterdaySub, OnSurface() }, { TR("mining_all_time"), allVal, allSub, OnSurface() }, - { TR("mining_est_daily"), estVal, estSub, estActive ? greenCol2 : OnSurfaceDisabled() }, + { TR("mining_est_daily"), estVal, estSub, estCol }, }; for (int ei = 0; ei < numCols; ei++) { @@ -223,6 +251,27 @@ void RenderMiningEarnings(App* app, const WalletState& state, const MiningInfo& ImVec2(centerX - valSz.x * 0.5f, valY), entries[ei].col, entries[ei].value); } } + + // Hover tooltip over the Est. Daily column (last column): explain the Poisson variance and, + // in pool mode, whether the figure is net of the fee. + { + float estColX = cardMin.x + pad + (numCols - 1) * colW; + ImVec2 estMin(estColX, ey); + ImVec2 estMax(estColX + colW, cardMin.y + earningsRowH); + if (material::IsRectHovered(estMin, estMax)) { + char tip[512]; + if (s_pool_mode && estFeePct > 0.0) { + char feeNote[160]; + snprintf(feeNote, sizeof(feeNote), TR("tt_mining_est_daily_fee_fmt"), estFeePct); + snprintf(tip, sizeof(tip), "%s\n%s", TR("tt_mining_est_daily"), feeNote); + } else if (s_pool_mode && estFeePct < 0.0) { // fee unknown (synthetic/unmatched pool) + snprintf(tip, sizeof(tip), "%s\n%s", TR("tt_mining_est_daily"), TR("tt_mining_est_daily_nofee")); + } else { // solo, or a known 0%-fee pool (net == gross) + snprintf(tip, sizeof(tip), "%s", TR("tt_mining_est_daily")); + } + material::Tooltip("%s", tip); + } + } } // === Separator between earnings & details === diff --git a/src/util/i18n.cpp b/src/util/i18n.cpp index 150f699..1434aa0 100644 --- a/src/util/i18n.cpp +++ b/src/util/i18n.cpp @@ -2184,6 +2184,11 @@ void I18n::loadBuiltinEnglish() strings_["mining_difficulty_copied"] = "Difficulty copied"; strings_["mining_est_block"] = "Est. Block"; strings_["mining_est_daily"] = "Est. Daily"; + strings_["mining_est_daily_sub"] = "avg"; + strings_["mining_est_daily_sub_net"] = "avg, net"; + strings_["tt_mining_est_daily"] = "A long-run statistical average for your current hashrate share of the network. Real mining rewards arrive at random (Poisson) - often nothing for long stretches, then a lump - so this is NOT a steady daily income."; + strings_["tt_mining_est_daily_fee_fmt"] = "Shown after the %.1f%% pool fee."; + strings_["tt_mining_est_daily_nofee"] = "Shown before the pool fee (fee unknown for this pool)."; strings_["mining_filter_all"] = "All"; strings_["mining_filter_tip_all"] = "Show all earnings"; strings_["mining_filter_tip_pool"] = "Show pool earnings only";