ysdcsad
This commit is contained in:
@@ -1254,7 +1254,6 @@
|
||||
).toUpperCase();
|
||||
return ledgerCurrency || currentMiningCurrency || currentSettings.crypto_currency || 'DOGE';
|
||||
})();
|
||||
const currentWalletMiningBalance = walletPurchasingPower(latestWalletSnapshot, currentMiningCurrency);
|
||||
const preferredCurrencyCodes = Array.isArray(currentSettings.preferred_currencies)
|
||||
? currentSettings.preferred_currencies.map((code) => String(code || '').toUpperCase()).filter(Boolean)
|
||||
: [];
|
||||
@@ -1305,14 +1304,6 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
selectedOfferType === 'crypto' &&
|
||||
!Number.isFinite(maxDogeFilter) &&
|
||||
!isOfferAvailableForWallet(offer, latestWalletSnapshot)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selectedOfferType === 'fiat' && !Number.isFinite(speedMin)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1331,7 +1322,18 @@
|
||||
|
||||
return true;
|
||||
});
|
||||
const scenarioMinerOffers = filteredMinerOffers;
|
||||
const pinnedReferenceMinerOffer = evaluatedMinerOffers.find((offer) => (
|
||||
String(offer.payment_type || '').toLowerCase() === 'crypto'
|
||||
&& Number(offer.runtime_months) === 36
|
||||
&& Math.abs(toKhPerSecond(offer.mining_speed_value, offer.mining_speed_unit) - 50) < 0.0001
|
||||
)) || null;
|
||||
const visibleMinerOffers = pinnedReferenceMinerOffer && !filteredMinerOffers.some((offer) => String(offer.id) === String(pinnedReferenceMinerOffer.id))
|
||||
? [{ ...pinnedReferenceMinerOffer, is_pinned_reference: true }].concat(filteredMinerOffers)
|
||||
: filteredMinerOffers.map((offer) => ({
|
||||
...offer,
|
||||
is_pinned_reference: pinnedReferenceMinerOffer !== null && String(offer.id) === String(pinnedReferenceMinerOffer.id),
|
||||
}));
|
||||
const scenarioMinerOffers = visibleMinerOffers;
|
||||
const preferredMinerOffer = currentSummaryMinerOffers
|
||||
.filter((offer) => String(offer.payment_type || '').toLowerCase() === 'crypto')
|
||||
.map((offer) => {
|
||||
@@ -1367,13 +1369,20 @@
|
||||
offer_hashrate_mh: targetOfferHashrateKh / 1000,
|
||||
};
|
||||
})();
|
||||
const resolvedPreferredMinerOffer = preferredMinerOffer || syntheticPreferredMinerOffer;
|
||||
const resolvedPreferredMinerOffer = pinnedReferenceMinerOffer || preferredMinerOffer || syntheticPreferredMinerOffer;
|
||||
const preferredOfferRequiredCoins = resolvedPreferredMinerOffer
|
||||
? convertCurrencyValue(
|
||||
resolvedPreferredMinerOffer.effective_price_amount ?? resolvedPreferredMinerOffer.crypto_display_price_amount ?? resolvedPreferredMinerOffer.usd_display_price_amount,
|
||||
resolvedPreferredMinerOffer.effective_price_currency || resolvedPreferredMinerOffer.crypto_display_price_currency || resolvedPreferredMinerOffer.usd_display_price_currency || currentMiningCurrency,
|
||||
currentMiningCurrency
|
||||
)
|
||||
? (() => {
|
||||
const directCryptoAmount = Number(resolvedPreferredMinerOffer.crypto_display_price_amount);
|
||||
const directCryptoCurrency = String(resolvedPreferredMinerOffer.crypto_display_price_currency || '').toUpperCase();
|
||||
if (Number.isFinite(directCryptoAmount) && directCryptoAmount > 0 && directCryptoCurrency === currentMiningCurrency) {
|
||||
return directCryptoAmount;
|
||||
}
|
||||
return convertCurrencyValue(
|
||||
resolvedPreferredMinerOffer.effective_price_amount ?? resolvedPreferredMinerOffer.crypto_display_price_amount ?? resolvedPreferredMinerOffer.usd_display_price_amount,
|
||||
resolvedPreferredMinerOffer.effective_price_currency || resolvedPreferredMinerOffer.crypto_display_price_currency || resolvedPreferredMinerOffer.usd_display_price_currency || currentMiningCurrency,
|
||||
currentMiningCurrency
|
||||
);
|
||||
})()
|
||||
: null;
|
||||
const preferredOfferCurrentCoins = payload?.summary?.payouts?.holdings_current_asset !== null
|
||||
&& payload?.summary?.payouts?.holdings_current_asset !== undefined
|
||||
@@ -1765,91 +1774,6 @@
|
||||
return rate === null ? null : numericValue * rate;
|
||||
}
|
||||
|
||||
function walletAssetBalance(snapshot, currency) {
|
||||
const code = String(currency || '').toUpperCase();
|
||||
if (!snapshot || !code) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const assets = snapshot.balances_json && typeof snapshot.balances_json === 'object' ? snapshot.balances_json : {};
|
||||
const asset = assets[code] ?? assets[code.toLowerCase()] ?? assets[code.toUpperCase()];
|
||||
const snapshotCurrency = String(snapshot.wallet_currency || '').toUpperCase();
|
||||
const rawBalance = asset && typeof asset === 'object'
|
||||
? asset.balance
|
||||
: (asset ?? (snapshotCurrency === code ? snapshot.wallet_balance : null));
|
||||
const balance = Number(rawBalance);
|
||||
return Number.isFinite(balance) ? balance : null;
|
||||
}
|
||||
|
||||
function walletPurchasingPower(snapshot, targetCurrency) {
|
||||
const target = String(targetCurrency || '').toUpperCase();
|
||||
if (!snapshot || !target) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const directBalance = walletAssetBalance(snapshot, target);
|
||||
if (Number.isFinite(directBalance)) {
|
||||
return directBalance;
|
||||
}
|
||||
|
||||
const totalValueAmount = Number(snapshot.total_value_amount);
|
||||
const totalValueCurrency = String(snapshot.total_value_currency || '').toUpperCase();
|
||||
if (Number.isFinite(totalValueAmount) && totalValueCurrency) {
|
||||
const convertedTotal = convertCurrencyValue(totalValueAmount, totalValueCurrency, target);
|
||||
if (Number.isFinite(convertedTotal)) {
|
||||
return convertedTotal;
|
||||
}
|
||||
}
|
||||
|
||||
const assets = snapshot.balances_json && typeof snapshot.balances_json === 'object' ? snapshot.balances_json : {};
|
||||
let total = 0;
|
||||
let matched = false;
|
||||
for (const [assetCode, assetValue] of Object.entries(assets)) {
|
||||
const normalizedCode = String(assetCode || '').toUpperCase();
|
||||
const balance = Number(assetValue && typeof assetValue === 'object' ? assetValue.balance : assetValue);
|
||||
const priceAmount = Number(assetValue && typeof assetValue === 'object' ? assetValue.price_amount : null);
|
||||
const priceCurrency = String(assetValue && typeof assetValue === 'object' ? assetValue.price_currency : '').toUpperCase();
|
||||
if (!normalizedCode || !Number.isFinite(balance) || balance <= 0) {
|
||||
continue;
|
||||
}
|
||||
if (normalizedCode === target) {
|
||||
total += balance;
|
||||
matched = true;
|
||||
continue;
|
||||
}
|
||||
if (Number.isFinite(priceAmount) && priceAmount > 0 && priceCurrency) {
|
||||
const assetValueInPriceCurrency = balance * priceAmount;
|
||||
const converted = convertCurrencyValue(assetValueInPriceCurrency, priceCurrency, target);
|
||||
if (Number.isFinite(converted)) {
|
||||
total += converted;
|
||||
matched = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matched ? total : null;
|
||||
}
|
||||
|
||||
function isOfferAvailableForWallet(offer, walletSnapshot) {
|
||||
if (!offer || !offer.is_active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (String(offer.payment_type || '').toLowerCase() !== 'crypto') {
|
||||
return true;
|
||||
}
|
||||
|
||||
const currency = String(offer.effective_price_currency || offer.price_currency || '').toUpperCase();
|
||||
const price = Number(offer.effective_price_amount);
|
||||
const balance = Number(walletPurchasingPower(walletSnapshot, currency));
|
||||
|
||||
if (!currency || !Number.isFinite(price) || !Number.isFinite(balance)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return price <= balance + 0.00000001;
|
||||
}
|
||||
|
||||
function latestFxHistoryRate(fromCurrency, toCurrency) {
|
||||
const from = String(fromCurrency || '').toUpperCase();
|
||||
const to = String(toCurrency || '').toUpperCase();
|
||||
@@ -2175,9 +2099,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
const effectivePrice = Number(row.effective_price_per_coin);
|
||||
const convertedPrice = Number.isFinite(effectivePrice)
|
||||
? convertMeasurementMoney(row, effectivePrice, reportCurrency)
|
||||
const rawPrice = row.effective_price_per_coin !== null && row.effective_price_per_coin !== undefined
|
||||
? row.effective_price_per_coin
|
||||
: row.price_per_coin;
|
||||
const sourcePrice = Number(rawPrice);
|
||||
const convertedPrice = Number.isFinite(sourcePrice) && sourcePrice > 0
|
||||
? convertMeasurementMoney(row, sourcePrice, reportCurrency)
|
||||
: null;
|
||||
if (!dayKey || !Number.isFinite(Number(convertedPrice))) {
|
||||
return;
|
||||
@@ -3853,9 +3780,7 @@
|
||||
renderMinerTable(inactiveMinerRows, 'Noch keine inaktiven Miner hinterlegt.'),
|
||||
]),
|
||||
panel('Miner-Angebote', selectedOfferType === 'crypto'
|
||||
? (currentWalletMiningBalance !== null
|
||||
? `Crypto-Angebote sind aktiv. Standardmäßig werden Laufzeiten ab ${fmtNumber(minOfferRuntimeMonths, 0)} Monaten berücksichtigt und nur Angebote gezeigt, die dein NC-Wallet aktuell tragen kann (${fmtNumber(currentWalletMiningBalance, 8)} ${currentMiningCurrency} Gegenwert).`
|
||||
: `Crypto-Angebote sind aktiv. Standardmäßig werden Laufzeiten ab ${fmtNumber(minOfferRuntimeMonths, 0)} Monaten berücksichtigt. Solange kein Wallet-Bestand erkannt wird, bleiben die Krypto-Angebote sichtbar.`)
|
||||
? `Crypto-Angebote sind aktiv. Standardmäßig werden Laufzeiten ab ${fmtNumber(minOfferRuntimeMonths, 0)} Monaten berücksichtigt. Der 50-kH/s-Server mit 36 Monaten bleibt als Referenz immer sichtbar; der Wallet-Bestand begrenzt weder Anzeige noch Mieten.`
|
||||
: `Fiat-Angebote sind aktiv. Standardmäßig werden Laufzeiten ab ${fmtNumber(minOfferRuntimeMonths, 0)} Monaten berücksichtigt. Die Berechnung startet erst, wenn du eine Geschwindigkeit eingibst.`,
|
||||
[
|
||||
h('div', { key: 'filters', className: 'mc-filter-grid' }, [
|
||||
@@ -3917,9 +3842,14 @@
|
||||
h('table', { key: 'table', className: 'mc-table' }, [
|
||||
h('thead', { key: 'head' }, h('tr', null, ['Label', 'Hashrate', 'Preis', 'Erwartet/Tag', 'Break-even', 'Empfehlung', 'Aktion'].map((label) => h('th', { key: label }, label)))),
|
||||
h('tbody', { key: 'body' },
|
||||
filteredMinerOffers.length
|
||||
? filteredMinerOffers.map((offer) => h('tr', { key: offer.id }, [
|
||||
h('td', { key: 'label' }, offer.label),
|
||||
visibleMinerOffers.length
|
||||
? visibleMinerOffers.map((offer) => h('tr', { key: offer.id }, [
|
||||
h('td', { key: 'label' }, [
|
||||
h('div', { key: 'name' }, offer.label),
|
||||
offer.is_pinned_reference
|
||||
? h('div', { key: 'reference', className: 'mc-kicker' }, 'Referenzangebot · 50 kH/s · 36 Monate')
|
||||
: null,
|
||||
]),
|
||||
h('td', { key: 'hashrate' }, [
|
||||
h('div', { key: 'base' }, formatSpeed(offer.mining_speed_value, offer.mining_speed_unit, 'Basis') || 'n/a'),
|
||||
Number(offer.bonus_speed_value) > 0
|
||||
@@ -3982,7 +3912,6 @@
|
||||
? h('div', { key: 'rec-ref', className: 'mc-kicker' }, `Basis ${fmtNumber(offer.base_price_amount, 6)} ${offer.base_price_currency}`)
|
||||
: null,
|
||||
offer.payment_type ? h('div', { key: 'paytype', className: 'mc-kicker' }, offer.payment_type === 'crypto' ? `Zahlung in Krypto (${currentSettings.crypto_currency || 'DOGE'})` : `Zahlung in FIAT (${offer.base_price_currency || 'EUR'})`) : null,
|
||||
h('div', { key: 'availability', className: 'mc-kicker' }, isOfferAvailableForWallet(offer, latestWalletSnapshot) ? 'Im NC Wallet verfuegbar' : 'Nicht genug NC Wallet Bestand'),
|
||||
h('div', { key: 'renew', className: 'mc-kicker' }, offer.auto_renew ? 'Automatische Verlängerung' : 'Laeuft aus'),
|
||||
]),
|
||||
h('td', { key: 'action' }, [
|
||||
@@ -4030,7 +3959,7 @@
|
||||
});
|
||||
setPurchaseMinerModalOpen(true);
|
||||
},
|
||||
disabled: !isOfferAvailableForWallet(offer, latestWalletSnapshot),
|
||||
disabled: saving,
|
||||
}, 'Mieten'),
|
||||
]),
|
||||
]))
|
||||
|
||||
@@ -6,6 +6,8 @@ Das Modul erfasst Mining-Messpunkte der aktuell konfigurierten Kryptowaehrung, a
|
||||
|
||||
Im Startseiten-Ueberblick zeigt die Kachel `DOGE Bestand` den direkten Wallet-Bestand, den nach Transfers bereinigten Miner-Bestand, deren Summe sowie den letzten Coin/USD-Kurs. Bei einer geaenderten Mining-Waehrung werden Beschriftung und Werte entsprechend dieser Waehrung gefuehrt.
|
||||
|
||||
Der Kursverlauf verwendet pro Upload dessen gespeicherten Kurs und zugeordnete historische FX-Referenz. Uploads ohne Kurs werden nicht als Kurs `0` dargestellt.
|
||||
|
||||
## Ordnerstruktur
|
||||
|
||||
```text
|
||||
@@ -120,6 +122,8 @@ Fuer Auswertungen, Berichte und Listen speichert der Mining-Checker pro Messpunk
|
||||
|
||||
Die Angebotsberechnung fuer Krypto-Miner nutzt eine konfigurierbare Basis fuer `50 kH/s` und `3 Monate`. Standard ist `5.49 USD`, kann aber in den Modul-Settings angepasst werden.
|
||||
|
||||
Unabhaengig von aktiven Angebots-, Wallet-, Preis- oder Laufzeitfiltern bleibt der Krypto-Server mit `50 kH/s` und `36 Monaten` als Referenzangebot in der Miner-Angebotsliste sichtbar. Die Zielminer-Kachel auf der Startseite verwendet denselben Angebotsdatensatz und dessen direkt berechneten Krypto-Preis. Der Walletbestand begrenzt weder Angebotsanzeige noch die Aktion `Mieten`, weil der Mietbetrag vor dem Speichern manuell angepasst werden kann.
|
||||
|
||||
Zusaetzlich koennen in den Settings diese Leitwerte hinterlegt werden:
|
||||
|
||||
- minimale gewuenschte Mietlaufzeit in Monaten
|
||||
|
||||
Reference in New Issue
Block a user