import chalk from "chalk" ; import { Algorithm } from "../Algorithm" ; import { HashRateUnit } from "../HashRateUnit" ; import * as NiceHash from "../apis/nicehash" ; import * as WhatToMine from "../apis/whattomine" ; import { AbstractHandler } from "../handlers" ; import * as requestLib from "../lib/request" ; import { logger } from "../logger" ; import { IOptions } from "../options" ; import { sleep } from "../utils" ; import { IHandlerData } from "./IHandlerData" ; import { ICoin , getCoins as getWhatToMineCoins } from "./coins" ; import { filter as filterCoins } from "./filter" ; import { listCoins } from "./listCoins" ; export class NiceHashCalculator { public options : IOptions ; private revenueCache : WhatToMine . IRevenueResponse [ ] = [ ] ; private priceCache : { [ s ] : number ; } = { } ; private outputHandler ! : AbstractHandler ; constructor ( options = { } as IOptions ) { this . options = options ; } public async start ( ) { const outputHandler = new this . options . outputHandler . class ( ) ; this . outputHandler = outputHandler ; this . initOptions ( ) ; await this . initApis ( ) ; const allCoins = await getWhatToMineCoins ( ) ; const coins = filterCoins ( allCoins , this . options . coins ) ; if ( this . options . listCoins ) { listCoins ( coins ) ; return ; } await this . populateWhatToMineCache ( coins ) ; for ( const coin of coins ) { const data = await this . handleCoin ( coin ) ; outputHandler . handle ( data , this ) ; const isLastCoin = coins . indexOf ( coin ) === coins . length - 1 ; if ( ! isLastCoin ) { await sleep ( this . options . sleepTime ) ; } } outputHandler . finished ( this ) ; } private async handleCoin ( coin ) { const revenueData = await this . getRevenue ( coin ) ; if ( this . options . includeFees ) { revenueData . revenue *= 0.97 ; } const revenue = revenueData . revenue ; const price = await this . getPrice ( coin . algorithm . niceHash ) ; const profit = revenue - price ; const returnOnInvestment = price === 0 ? 0 : revenue / price ; const percentChange = returnOnInvestment - 1 ; const data = { coin , revenue , rawRevenue : revenueData , price , profit , returnOnInvestment , percentChange , } ; return data ; } private initOptions ( ) { logger . showWarnings = this . options . showWarnings ; logger . debugEnabled = this . options . debug ; logger . debug ( "options" , this . options ) ; requestLib . config . pretty . enabled = this . outputHandler . pretty ; for ( const unrecognizedOption of this . options . unrecognized ) { logger . warn ( "Unrecognized option: " + unrecognizedOption ) ; } if ( this . options . includeFees ) { logger . warn ( "Accounting for NiceHash's 3% fee. This is experimental. Please be aware of the additional 0.0001 BTC fee that is not accounted for here." ) ; } } private async initApis ( ) { const buyerInfo = await NiceHash . getBuyerInfo ( ) ; const algorithms = buyerInfo . miningAlgorithms ; for ( const nhMeta of algorithms ) { const hashrate = nhMeta . speed_text ; const id = + nhMeta . algo ; for ( const algo of Algorithm . instances ) { if ( algo . idNum === id ) { const algorithm = new NiceHash . Algorithm ( algo . idEnum , HashRateUnit . fromString ( hashrate ) ) ; algo . niceHash = algorithm ; logger . debug ( `initApis(): set unit for ${ algo . displayName } to ${ algorithm . unit . displayName }` ) ; break ; } } } if ( logger . debugEnabled ) { for ( const algo of Algorithm . instances ) { if ( ! algo . niceHash ) { logger . warn ( `Missing metadata for algorithm ${ algo . displayName } (${ algo . idEnum })` ) ; } } } } private async populateWhatToMineCache ( coins ) { const activeAlgorithms = new Set ( coins . map ( ( coin ) => coin . algorithm ) ) ; const getOptions = ( ) => { const result = [ ] ; for ( const algo of activeAlgorithms ) { if ( ! algo . whatToMine . cacheNames ) { continue ; } result . push ( { algorithm : algo . whatToMine , hashrate : this . getWhatToMineHashrate ( algo ) , } ) ; } return result ; } ; const algos = getOptions ( ) ; if ( algos . length === 0 ) { return ; } const cache = await WhatToMine . getListedCoins ( algos ) ; this . revenueCache = cache ; } private getWhatToMineHashrate ( algorithm ) { return algorithm . niceHash . unit . hashes / algorithm . whatToMine . unit . hashes ; } private async getPrice ( algo ) { if ( this . priceCache [ algo . id ] !== undefined ) { return this . priceCache [ algo . id ] ; } else { const price = await NiceHash . getPrice ( algo , this . options . prices ) ; this . priceCache [ algo . id ] = price ; return price ; } } private async getRevenue ( coin ) { if ( this . revenueCache [ coin . id ] ) { return this . revenueCache [ coin . id ] ; } else { return await WhatToMine . getRevenue ( coin . id , this . getWhatToMineHashrate ( coin . algorithm ) ) ; } } }