ysdcsad
This commit is contained in:
@@ -1254,7 +1254,6 @@
|
|||||||
).toUpperCase();
|
).toUpperCase();
|
||||||
return ledgerCurrency || currentMiningCurrency || currentSettings.crypto_currency || 'DOGE';
|
return ledgerCurrency || currentMiningCurrency || currentSettings.crypto_currency || 'DOGE';
|
||||||
})();
|
})();
|
||||||
const currentWalletMiningBalance = walletPurchasingPower(latestWalletSnapshot, currentMiningCurrency);
|
|
||||||
const preferredCurrencyCodes = Array.isArray(currentSettings.preferred_currencies)
|
const preferredCurrencyCodes = Array.isArray(currentSettings.preferred_currencies)
|
||||||
? currentSettings.preferred_currencies.map((code) => String(code || '').toUpperCase()).filter(Boolean)
|
? currentSettings.preferred_currencies.map((code) => String(code || '').toUpperCase()).filter(Boolean)
|
||||||
: [];
|
: [];
|
||||||
@@ -1305,14 +1304,6 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
|
||||||
selectedOfferType === 'crypto' &&
|
|
||||||
!Number.isFinite(maxDogeFilter) &&
|
|
||||||
!isOfferAvailableForWallet(offer, latestWalletSnapshot)
|
|
||||||
) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedOfferType === 'fiat' && !Number.isFinite(speedMin)) {
|
if (selectedOfferType === 'fiat' && !Number.isFinite(speedMin)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1331,7 +1322,18 @@
|
|||||||
|
|
||||||
return true;
|
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
|
const preferredMinerOffer = currentSummaryMinerOffers
|
||||||
.filter((offer) => String(offer.payment_type || '').toLowerCase() === 'crypto')
|
.filter((offer) => String(offer.payment_type || '').toLowerCase() === 'crypto')
|
||||||
.map((offer) => {
|
.map((offer) => {
|
||||||
@@ -1367,13 +1369,20 @@
|
|||||||
offer_hashrate_mh: targetOfferHashrateKh / 1000,
|
offer_hashrate_mh: targetOfferHashrateKh / 1000,
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
const resolvedPreferredMinerOffer = preferredMinerOffer || syntheticPreferredMinerOffer;
|
const resolvedPreferredMinerOffer = pinnedReferenceMinerOffer || preferredMinerOffer || syntheticPreferredMinerOffer;
|
||||||
const preferredOfferRequiredCoins = resolvedPreferredMinerOffer
|
const preferredOfferRequiredCoins = resolvedPreferredMinerOffer
|
||||||
? convertCurrencyValue(
|
? (() => {
|
||||||
resolvedPreferredMinerOffer.effective_price_amount ?? resolvedPreferredMinerOffer.crypto_display_price_amount ?? resolvedPreferredMinerOffer.usd_display_price_amount,
|
const directCryptoAmount = Number(resolvedPreferredMinerOffer.crypto_display_price_amount);
|
||||||
resolvedPreferredMinerOffer.effective_price_currency || resolvedPreferredMinerOffer.crypto_display_price_currency || resolvedPreferredMinerOffer.usd_display_price_currency || currentMiningCurrency,
|
const directCryptoCurrency = String(resolvedPreferredMinerOffer.crypto_display_price_currency || '').toUpperCase();
|
||||||
currentMiningCurrency
|
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;
|
: null;
|
||||||
const preferredOfferCurrentCoins = payload?.summary?.payouts?.holdings_current_asset !== null
|
const preferredOfferCurrentCoins = payload?.summary?.payouts?.holdings_current_asset !== null
|
||||||
&& payload?.summary?.payouts?.holdings_current_asset !== undefined
|
&& payload?.summary?.payouts?.holdings_current_asset !== undefined
|
||||||
@@ -1765,91 +1774,6 @@
|
|||||||
return rate === null ? null : numericValue * rate;
|
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) {
|
function latestFxHistoryRate(fromCurrency, toCurrency) {
|
||||||
const from = String(fromCurrency || '').toUpperCase();
|
const from = String(fromCurrency || '').toUpperCase();
|
||||||
const to = String(toCurrency || '').toUpperCase();
|
const to = String(toCurrency || '').toUpperCase();
|
||||||
@@ -2175,9 +2099,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const effectivePrice = Number(row.effective_price_per_coin);
|
const rawPrice = row.effective_price_per_coin !== null && row.effective_price_per_coin !== undefined
|
||||||
const convertedPrice = Number.isFinite(effectivePrice)
|
? row.effective_price_per_coin
|
||||||
? convertMeasurementMoney(row, effectivePrice, reportCurrency)
|
: row.price_per_coin;
|
||||||
|
const sourcePrice = Number(rawPrice);
|
||||||
|
const convertedPrice = Number.isFinite(sourcePrice) && sourcePrice > 0
|
||||||
|
? convertMeasurementMoney(row, sourcePrice, reportCurrency)
|
||||||
: null;
|
: null;
|
||||||
if (!dayKey || !Number.isFinite(Number(convertedPrice))) {
|
if (!dayKey || !Number.isFinite(Number(convertedPrice))) {
|
||||||
return;
|
return;
|
||||||
@@ -3853,9 +3780,7 @@
|
|||||||
renderMinerTable(inactiveMinerRows, 'Noch keine inaktiven Miner hinterlegt.'),
|
renderMinerTable(inactiveMinerRows, 'Noch keine inaktiven Miner hinterlegt.'),
|
||||||
]),
|
]),
|
||||||
panel('Miner-Angebote', selectedOfferType === 'crypto'
|
panel('Miner-Angebote', selectedOfferType === 'crypto'
|
||||||
? (currentWalletMiningBalance !== null
|
? `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.`
|
||||||
? `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.`)
|
|
||||||
: `Fiat-Angebote sind aktiv. Standardmäßig werden Laufzeiten ab ${fmtNumber(minOfferRuntimeMonths, 0)} Monaten berücksichtigt. Die Berechnung startet erst, wenn du eine Geschwindigkeit eingibst.`,
|
: `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' }, [
|
h('div', { key: 'filters', className: 'mc-filter-grid' }, [
|
||||||
@@ -3917,9 +3842,14 @@
|
|||||||
h('table', { key: 'table', className: 'mc-table' }, [
|
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('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' },
|
h('tbody', { key: 'body' },
|
||||||
filteredMinerOffers.length
|
visibleMinerOffers.length
|
||||||
? filteredMinerOffers.map((offer) => h('tr', { key: offer.id }, [
|
? visibleMinerOffers.map((offer) => h('tr', { key: offer.id }, [
|
||||||
h('td', { key: 'label' }, offer.label),
|
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('td', { key: 'hashrate' }, [
|
||||||
h('div', { key: 'base' }, formatSpeed(offer.mining_speed_value, offer.mining_speed_unit, 'Basis') || 'n/a'),
|
h('div', { key: 'base' }, formatSpeed(offer.mining_speed_value, offer.mining_speed_unit, 'Basis') || 'n/a'),
|
||||||
Number(offer.bonus_speed_value) > 0
|
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}`)
|
? h('div', { key: 'rec-ref', className: 'mc-kicker' }, `Basis ${fmtNumber(offer.base_price_amount, 6)} ${offer.base_price_currency}`)
|
||||||
: null,
|
: 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,
|
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('div', { key: 'renew', className: 'mc-kicker' }, offer.auto_renew ? 'Automatische Verlängerung' : 'Laeuft aus'),
|
||||||
]),
|
]),
|
||||||
h('td', { key: 'action' }, [
|
h('td', { key: 'action' }, [
|
||||||
@@ -4030,7 +3959,7 @@
|
|||||||
});
|
});
|
||||||
setPurchaseMinerModalOpen(true);
|
setPurchaseMinerModalOpen(true);
|
||||||
},
|
},
|
||||||
disabled: !isOfferAvailableForWallet(offer, latestWalletSnapshot),
|
disabled: saving,
|
||||||
}, 'Mieten'),
|
}, '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.
|
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
|
## Ordnerstruktur
|
||||||
|
|
||||||
```text
|
```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.
|
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:
|
Zusaetzlich koennen in den Settings diese Leitwerte hinterlegt werden:
|
||||||
|
|
||||||
- minimale gewuenschte Mietlaufzeit in Monaten
|
- minimale gewuenschte Mietlaufzeit in Monaten
|
||||||
|
|||||||
Reference in New Issue
Block a user