diff --git a/CREDITS.md b/CREDITS.md index 58b4139..714c1b1 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -3,7 +3,9 @@ * [fireice-uk's and psychocrypt's Xmr-Stak](https://github.com/fireice-uk/xmr-stak) * [Gandalph3000's Cast XMR](http://www.gandalph3000.com/) * [doktor83's SRBMiner](https://bitcointalk.org/index.php?topic=3167363.0) +* [JCE Miner](https://bitcointalk.org/index.php?topic=3281187.0) * [MineCryptoNight API](http://minecryptonight.net/api) +* [CryptUnit API](https://www.cryptunit.com/api/) * [miner.rocks API](https://miner.rocks/) * [cryptoknight.cc API](https://cryptoknight.cc/) * [MoneroOcean API](https://moneroocean.stream) diff --git a/Coins/Aeon.json b/Coins/Aeon.json index 2c00aa9..59ddeae 100644 --- a/Coins/Aeon.json +++ b/Coins/Aeon.json @@ -7,7 +7,7 @@ "TickerSymbol": "AEON", // Mining algorithm of coin, can be CryptonightV7, CryptonightHeavy, CryptonightLite, CryptonightBittube, CryptonightStellite, CryptonightHaven or CryptonightMasari "Algorithm": "CryptonightLite", - // Used Miner, can be XmrStak, CastXmr or SRBMiner (Recommended: XmrStak) + // Used Miner, can be XmrStak, CastXmr, SRBMiner or JceMiner (Recommended: XmrStak) "Miner": "XmrStak", // Path to script that runs before the miner starts, can be null. // For example:: Path to batch file that sets specific OverdriveN settings for this coin @@ -21,7 +21,7 @@ "OverrideExpectedHashrate": null, // Override the profit timeframe, can be Live, Day or null. "OverrideProfitTimeframe": null, - // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, MinerRocksApi, CryptoknightCCApi) or null. + // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, CryptunitApi, MinerRocksApi, CryptoknightCCApi) or null. "OverridePoolProfitProviders": null, // On the determination of the most profitable coin, the actual estimated profit will be multiplied by this, can be a decimal or null. "PreferFactor": 1.0, @@ -75,7 +75,14 @@ // Extra arguments that will be passed over to SRBMiner, can be a string or null "SRBMinerExtraArguments": null, // Set if you want to also start Xmr-Stak for CPU Mining - "SRBMinerUseXmrStakCPUMining": true + "SRBMinerUseXmrStakCPUMining": true, + /* JCEMINER CONFIGURATION - NEEDED IF MINER IS JCEMINER */ + // Path to JceMiner executable + "JceMinerPath": "JceMiner/jce_cn_gpu_miner64.exe", + // Path to JceMiner config (can be null <- then auto configuration will be used) + "JceMinerConfig": "JceMiner/config_lite.txt", + // Extra arguments for JceMiner + "JceMinerExtraArguments": null } diff --git a/Coins/Bittube.json b/Coins/Bittube.json index 56adea2..838f6a8 100644 --- a/Coins/Bittube.json +++ b/Coins/Bittube.json @@ -7,7 +7,7 @@ "TickerSymbol": "TUBE", // Mining algorithm of coin, can be CryptonightV7, CryptonightHeavy, CryptonightLite, CryptonightBittube, CryptonightStellite, CryptonightHaven or CryptonightMasari "Algorithm": "CryptonightBittube", - // Used Miner, can be XmrStak, CastXmr or SRBMiner + // Used Miner, can be XmrStak, CastXmr, SRBMiner or JceMiner "Miner": "XmrStak", // Path to script that runs before the miner starts, can be null. // For example:: Path to batch file that sets specific OverdriveN settings for this coin @@ -21,7 +21,7 @@ "OverrideExpectedHashrate": null, // Override the profit timeframe, can be Live, Day or null. "OverrideProfitTimeframe": null, - // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, MinerRocksApi, CryptoknightCCApi) or null. + // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, CryptunitApi, MinerRocksApi, CryptoknightCCApi) or null. "OverridePoolProfitProviders": null, // On the determination of the most profitable coin, the actual estimated profit will be multiplied by this, can be a decimal or null. "PreferFactor": 1.0, @@ -75,6 +75,15 @@ // Extra arguments that will be passed over to SRBMiner, can be a string or null "SRBMinerExtraArguments": null, // Set if you want to also start Xmr-Stak for CPU Mining - "SRBMinerUseXmrStakCPUMining": true + "SRBMinerUseXmrStakCPUMining": true, + + /* JCEMINER CONFIGURATION - NEEDED IF MINER IS JCEMINER */ + + // Path to JceMiner executable + "JceMinerPath": "JceMiner/jce_cn_gpu_miner64.exe", + // Path to JceMiner config (can be null <- then auto configuration will be used) + "JceMinerConfig": "JceMiner/config_heavy.txt", + // Extra arguments for JceMiner + "JceMinerExtraArguments": null } diff --git a/Coins/Graft.json b/Coins/Graft.json index 8cfed9f..8ef89af 100644 --- a/Coins/Graft.json +++ b/Coins/Graft.json @@ -7,7 +7,7 @@ "TickerSymbol": "GRFT", // Mining algorithm of coin, can be CryptonightV7, CryptonightHeavy, CryptonightLite, CryptonightBittube, CryptonightStellite, CryptonightHaven or CryptonightMasari "Algorithm": "CryptonightV7", - // Used Miner, can be XmrStak, CastXmr or SRBMiner (Recommended: XmrStak) + // Used Miner, can be XmrStak, CastXmr, SRBMiner or JceMiner (Recommended: XmrStak) "Miner": "XmrStak", // Path to script that runs before the miner starts, can be null. // For example:: Path to batch file that sets specific OverdriveN settings for this coin @@ -21,7 +21,7 @@ "OverrideExpectedHashrate": null, // Override the profit timeframe, can be Live, Day or null. "OverrideProfitTimeframe": null, - // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, MinerRocksApi, CryptoknightCCApi) or null. + // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, CryptunitApi, MinerRocksApi, CryptoknightCCApi) or null. "OverridePoolProfitProviders": null, // On the determination of the most profitable coin, the actual estimated profit will be multiplied by this, can be a decimal or null. "PreferFactor": 1.0, @@ -75,6 +75,15 @@ // Extra arguments that will be passed over to SRBMiner, can be a string or null "SRBMinerExtraArguments": null, // Set if you want to also start Xmr-Stak for CPU Mining - "SRBMinerUseXmrStakCPUMining": true + "SRBMinerUseXmrStakCPUMining": true, + + /* JCEMINER CONFIGURATION - NEEDED IF MINER IS JCEMINER */ + + // Path to JceMiner executable + "JceMinerPath": "JceMiner/jce_cn_gpu_miner64.exe", + // Path to JceMiner config (can be null <- then auto configuration will be used) + "JceMinerConfig": "JceMiner/config_v7.txt", + // Extra arguments for JceMiner + "JceMinerExtraArguments": null } diff --git a/Coins/Haven.json b/Coins/Haven.json index 7f6c7f6..8ded1f3 100644 --- a/Coins/Haven.json +++ b/Coins/Haven.json @@ -7,7 +7,7 @@ "TickerSymbol": "XHV", // Mining algorithm of coin, can be CryptonightV7, CryptonightHeavy, CryptonightLite, CryptonightBittube, CryptonightStellite, CryptonightHaven or CryptonightMasari "Algorithm": "CryptonightHaven", - // Used Miner, can be XmrStak, CastXmr or SRBMiner (Recommended: XmrStak) + // Used Miner, can be XmrStak, CastXmr, SRBMiner or JceMiner (Recommended: XmrStak) "Miner": "XmrStak", // Path to script that runs before the miner starts, can be null. // For example:: Path to batch file that sets specific OverdriveN settings for this coin @@ -21,7 +21,7 @@ "OverrideExpectedHashrate": null, // Override the profit timeframe, can be Live, Day or null. "OverrideProfitTimeframe": null, - // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, MinerRocksApi, CryptoknightCCApi) or null. + // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, CryptunitApi, MinerRocksApi, CryptoknightCCApi) or null. "OverridePoolProfitProviders": null, // On the determination of the most profitable coin, the actual estimated profit will be multiplied by this, can be a decimal or null. "PreferFactor": 1.0, @@ -75,7 +75,16 @@ // Extra arguments that will be passed over to SRBMiner, can be a string or null "SRBMinerExtraArguments": null, // Set if you want to also start Xmr-Stak for CPU Mining - "SRBMinerUseXmrStakCPUMining": true + "SRBMinerUseXmrStakCPUMining": true, + + /* JCEMINER CONFIGURATION - NEEDED IF MINER IS JCEMINER */ + + // Path to JceMiner executable + "JceMinerPath": "JceMiner/jce_cn_gpu_miner64.exe", + // Path to JceMiner config (can be null <- then auto configuration will be used) + "JceMinerConfig": "JceMiner/config_heavy.txt", + // Extra arguments for JceMiner + "JceMinerExtraArguments": null } diff --git a/Coins/Loki.json b/Coins/Loki.json index eba2ddd..d9560b8 100644 --- a/Coins/Loki.json +++ b/Coins/Loki.json @@ -7,7 +7,7 @@ "TickerSymbol": "LOKI", // Mining algorithm of coin, can be CryptonightV7, CryptonightHeavy, CryptonightLite, CryptonightBittube, CryptonightStellite, CryptonightHaven or CryptonightMasari "Algorithm": "CryptonightHeavy", - // Used Miner, can be XmrStak, CastXmr or SRBMiner (Recommended: XmrStak) + // Used Miner, can be XmrStak, CastXmr, SRBMiner or JceMiner (Recommended: XmrStak) "Miner": "XmrStak", // Path to script that runs before the miner starts, can be null. // For example:: Path to batch file that sets specific OverdriveN settings for this coin @@ -21,7 +21,7 @@ "OverrideExpectedHashrate": null, // Override the profit timeframe, can be Live, Day or null. "OverrideProfitTimeframe": null, - // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, MinerRocksApi, CryptoknightCCApi) or null. + // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, CryptunitApi, MinerRocksApi, CryptoknightCCApi) or null. "OverridePoolProfitProviders": null, // On the determination of the most profitable coin, the actual estimated profit will be multiplied by this, can be a decimal or null. "PreferFactor": 1.0, @@ -75,7 +75,16 @@ // Extra arguments that will be passed over to SRBMiner, can be a string or null "SRBMinerExtraArguments": null, // Set if you want to also start Xmr-Stak for CPU Mining - "SRBMinerUseXmrStakCPUMining": true + "SRBMinerUseXmrStakCPUMining": true, + + /* JCEMINER CONFIGURATION - NEEDED IF MINER IS JCEMINER */ + + // Path to JceMiner executable + "JceMinerPath": "JceMiner/jce_cn_gpu_miner64.exe", + // Path to JceMiner config (can be null <- then auto configuration will be used) + "JceMinerConfig": "JceMiner/config_heavy.txt", + // Extra arguments for JceMiner + "JceMinerExtraArguments": null } diff --git a/Coins/Masari.json b/Coins/Masari.json index 7d7210f..17f08b5 100644 --- a/Coins/Masari.json +++ b/Coins/Masari.json @@ -7,7 +7,7 @@ "TickerSymbol": "MSR", // Mining algorithm of coin, can be CryptonightV7, CryptonightHeavy, CryptonightLite, CryptonightBittube, CryptonightStellite, CryptonightHaven or CryptonightMasari "Algorithm": "CryptonightMasari", - // Used Miner, can be XmrStak, CastXmr or SRBMiner (Recommended: XmrStak) + // Used Miner, can be XmrStak, CastXmr, SRBMiner or JceMiner (Recommended: XmrStak) "Miner": "XmrStak", // Path to script that runs before the miner starts, can be null. // For example:: Path to batch file that sets specific OverdriveN settings for this coin @@ -21,7 +21,7 @@ "OverrideExpectedHashrate": 8420, // Override the profit timeframe, can be Live, Day or null. "OverrideProfitTimeframe": null, - // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, MinerRocksApi, CryptoknightCCApi) or null. + // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, CryptunitApi, MinerRocksApi, CryptoknightCCApi) or null. "OverridePoolProfitProviders": null, // On the determination of the most profitable coin, the actual estimated profit will be multiplied by this, can be a decimal or null. "PreferFactor": 1.0, @@ -75,7 +75,16 @@ // Extra arguments that will be passed over to SRBMiner, can be a string or null "SRBMinerExtraArguments": null, // Set if you want to also start Xmr-Stak for CPU Mining - "SRBMinerUseXmrStakCPUMining": true + "SRBMinerUseXmrStakCPUMining": true, + + /* JCEMINER CONFIGURATION - NEEDED IF MINER IS JCEMINER */ + + // Path to JceMiner executable + "JceMinerPath": "JceMiner/jce_cn_gpu_miner64.exe", + // Path to JceMiner config (can be null <- then auto configuration will be used) + "JceMinerConfig": "JceMiner/config_v7.txt", + // Extra arguments for JceMiner + "JceMinerExtraArguments": null } diff --git a/Coins/Monero.json b/Coins/Monero.json index 25fd932..96934ab 100644 --- a/Coins/Monero.json +++ b/Coins/Monero.json @@ -7,7 +7,7 @@ "TickerSymbol": "XMR", // Mining algorithm of coin, can be CryptonightV7, CryptonightHeavy, CryptonightLite, CryptonightBittube, CryptonightStellite, CryptonightHaven or CryptonightMasari "Algorithm": "CryptonightV7", - // Used Miner, can be XmrStak, CastXmr or SRBMiner (Recommended: XmrStak) + // Used Miner, can be XmrStak, CastXmr, SRBMiner or JceMiner (Recommended: XmrStak) "Miner": "XmrStak", // Path to script that runs before the miner starts, can be null. // For example:: Path to batch file that sets specific OverdriveN settings for this coin @@ -21,7 +21,7 @@ "OverrideExpectedHashrate": null, // Override the profit timeframe, can be Live, Day or null. "OverrideProfitTimeframe": null, - // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, MinerRocksApi, CryptoknightCCApi) or null. + // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, CryptunitApi, MinerRocksApi, CryptoknightCCApi) or null. "OverridePoolProfitProviders": null, // On the determination of the most profitable coin, the actual estimated profit will be multiplied by this, can be a decimal or null. "PreferFactor": 1.0, @@ -75,6 +75,15 @@ // Extra arguments that will be passed over to SRBMiner, can be a string or null "SRBMinerExtraArguments": null, // Set if you want to also start Xmr-Stak for CPU Mining - "SRBMinerUseXmrStakCPUMining": true + "SRBMinerUseXmrStakCPUMining": true, + + /* JCEMINER CONFIGURATION - NEEDED IF MINER IS JCEMINER */ + + // Path to JceMiner executable + "JceMinerPath": "JceMiner/jce_cn_gpu_miner64.exe", + // Path to JceMiner config (can be null <- then auto configuration will be used) + "JceMinerConfig": "JceMiner/config_v7.txt", + // Extra arguments for JceMiner + "JceMinerExtraArguments": null } diff --git a/Coins/MoneroOcean.json b/Coins/MoneroOcean.json index 0a2fddc..cf3c081 100644 --- a/Coins/MoneroOcean.json +++ b/Coins/MoneroOcean.json @@ -7,7 +7,7 @@ "TickerSymbol": "MoneroOcean", // Mining algorithm of coin, can be CryptonightV7, CryptonightHeavy, CryptonightLite, CryptonightBittube, CryptonightStellite, CryptonightHaven or CryptonightMasari "Algorithm": "CryptonightV7", - // Used Miner, can be XmrStak, CastXmr or SRBMiner (Recommended: XmrStak) + // Used Miner, can be XmrStak, CastXmr, SRBMiner or JceMiner (Recommended: XmrStak) "Miner": "XmrStak", // Path to script that runs before the miner starts, can be null. // For example:: Path to batch file that sets specific OverdriveN settings for this coin @@ -21,7 +21,7 @@ "OverrideExpectedHashrate": null, // Override the profit timeframe, can be Live, Day or null. "OverrideProfitTimeframe": null, - // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, MinerRocksApi, CryptoknightCCApi) or null. + // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, CryptunitApi, MinerRocksApi, CryptoknightCCApi) or null. "OverridePoolProfitProviders": "MoneroOceanApi", // On the determination of the most profitable coin, the actual estimated profit will be multiplied by this, can be a decimal or null. "PreferFactor": 1.05, @@ -75,6 +75,15 @@ // Extra arguments that will be passed over to SRBMiner, can be a string or null "SRBMinerExtraArguments": null, // Set if you want to also start Xmr-Stak for CPU Mining - "SRBMinerUseXmrStakCPUMining": true + "SRBMinerUseXmrStakCPUMining": true, + + /* JCEMINER CONFIGURATION - NEEDED IF MINER IS JCEMINER */ + + // Path to JceMiner executable + "JceMinerPath": "JceMiner/jce_cn_gpu_miner64.exe", + // Path to JceMiner config (can be null <- then auto configuration will be used) + "JceMinerConfig": "JceMiner/config_v7.txt", + // Extra arguments for JceMiner + "JceMinerExtraArguments": null } diff --git a/Coins/Quantum.json b/Coins/Quantum.json new file mode 100644 index 0000000..5cbf6d3 --- /dev/null +++ b/Coins/Quantum.json @@ -0,0 +1,89 @@ +{ + /* GENERAL CONFIGURATION - ALWAYS NEEDED */ + + // Displayed name, can be anything. + "DisplayName": "Quantum", + // Ticker symbol on minecryptonight.net, needed to get profit data + "TickerSymbol": "QRL", + // Mining algorithm of coin, can be CryptonightV7, CryptonightHeavy, CryptonightLite, CryptonightBittube, CryptonightStellite, CryptonightHaven or CryptonightMasari + "Algorithm": "CryptonightV7", + // Used Miner, can be XmrStak, CastXmr, SRBMiner or JceMiner (Recommended: XmrStak) + "Miner": "XmrStak", + // Path to script that runs before the miner starts, can be null. + // For example:: Path to batch file that sets specific OverdriveN settings for this coin + "PrepareScript": null, + // Enables or disables this coin, can be true or false (default: true) + "Enabled": true, + + /* OVERRIDE SETTINGS - NOT NEEDED */ + + // Override the expected hashrate, can be a number or null. + "OverrideExpectedHashrate": null, + // Override the profit timeframe, can be Live, Day or null. + "OverrideProfitTimeframe": null, + // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, CryptunitApi, MinerRocksApi, CryptoknightCCApi) or null. + "OverridePoolProfitProviders": null, + // On the determination of the most profitable coin, the actual estimated profit will be multiplied by this, can be a decimal or null. + "PreferFactor": 1.0, + + /* AUTO POOL CONFIGURATION - NEEDED FOR CASTXMR OR IF POOL CONFIG FILE IS NOT DIRECTLY SET */ + + "PoolAddress": "qrl.miner.rocks:5555", + "PoolWalletAddress": "0x01d47cc4f56ec05e735b316742459eeef08d5867", + "PoolPassword": "x", + "PoolUseTls": false, + "PoolTlsFingerprint": "", + "PoolWeight": 1, + "PoolRigId": "", + + /* XMR-STAK CONFIGURATION - NEEDED IF MINER IS XMRSTAK OR FOR CPU MINING*/ + + // Path to Xmr-Stak executable + "XmrStakPath": "$PlatformSpecificXmrStakPath", + // Path to Xmr-Stak config file + "ConfigPath": "XmrStak/config.txt", + // Port of the Xmr-Stak Json API, should match the port in the config file of Xmr-Stak. + "XmrStakApiPort": 4000, + // Path to Xmr-Stak cpu config file, can be null. + "CpuPath": "XmrStak/cpu_v7.txt", + // Path to Xmr-Stak amd gpu config file, can be null. + "AmdPath": "XmrStak/amd_v7.txt", + // Path to Xmr-Stak nvidea gpu config file, can be null. + "NvidiaPath": null, + // Set the path to Xmr-Stak pool config file directly (can be null, if you use AUTO POOL CONFIGURATION) + "PoolsPath": null, + + /* CASTXMR CONFIGURATION - NEEDED IF MINER IS CASTXMR */ + + // Path to CastXmr executable + "CastXmrPath": "CastXmr/cast_xmr-vega.exe", + // Extra arguments for setting the GPUs or tuning + "CastXmrExtraArguments": "-G 0,1", + // Set if you want to also start Xmr-Stak for CPU Mining + "CastXmrUseXmrStakCPUMining": true, + + /* SRBMINER CONFIGURATION - NEEDED IF MINER IS SRBMINER*/ + + // Path to SRBMiner executable + "SRBMinerPath": "SRBMiner/SRBMiner-CN.exe", + // Path to SRBMiner config file + "SRBMinerConfigPath": "SRBMiner/config_v7.txt", + // Port of the SRBMiner REST API, should match the port in the config file of SRBMiner. + "SRBMinerApiPort": 21555, + // Set the path to SRBMiner pool config file directly (can be null, if you use AUTO POOL CONFIGURATION) + "SRBMinerPoolsPath": null, + // Extra arguments that will be passed over to SRBMiner, can be a string or null + "SRBMinerExtraArguments": null, + // Set if you want to also start Xmr-Stak for CPU Mining + "SRBMinerUseXmrStakCPUMining": true, + + /* JCEMINER CONFIGURATION - NEEDED IF MINER IS JCEMINER */ + + // Path to JceMiner executable + "JceMinerPath": "JceMiner/jce_cn_gpu_miner64.exe", + // Path to JceMiner config (can be null <- then auto configuration will be used) + "JceMinerConfig": "JceMiner/config_v7.txt", + // Extra arguments for JceMiner + "JceMinerExtraArguments": null + +} diff --git a/Coins/Stellite.json b/Coins/Stellite.json index 49272d2..a9bbd44 100644 --- a/Coins/Stellite.json +++ b/Coins/Stellite.json @@ -7,7 +7,7 @@ "TickerSymbol": "XTL", // Mining algorithm of coin, can be CryptonightV7, CryptonightHeavy, CryptonightLite, CryptonightBittube, CryptonightStellite, CryptonightHaven or CryptonightMasari "Algorithm": "CryptonightStellite", - // Used Miner, can be XmrStak, CastXmr or SRBMiner (Recommended: XmrStak) + // Used Miner, can be XmrStak, CastXmr, SRBMiner or JceMiner (Recommended: XmrStak) "Miner": "XmrStak", // Path to script that runs before the miner starts, can be null. // For example:: Path to batch file that sets specific OverdriveN settings for this coin @@ -21,7 +21,7 @@ "OverrideExpectedHashrate": null, // Override the profit timeframe, can be Live, Day or null. "OverrideProfitTimeframe": null, - // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, MinerRocksApi, CryptoknightCCApi) or null. + // Override the profit providers, can be a comma seperated ordered string (example: MineCryptonightApi, CryptunitApi, MinerRocksApi, CryptoknightCCApi) or null. "OverridePoolProfitProviders": null, // On the determination of the most profitable coin, the actual estimated profit will be multiplied by this, can be a decimal or null. "PreferFactor": 1.0, @@ -75,7 +75,16 @@ // Extra arguments that will be passed over to SRBMiner, can be a string or null "SRBMinerExtraArguments": null, // Set if you want to also start Xmr-Stak for CPU Mining - "SRBMinerUseXmrStakCPUMining": true + "SRBMinerUseXmrStakCPUMining": true, + + /* JCEMINER CONFIGURATION - NEEDED IF MINER IS JCEMINER */ + + // Path to JceMiner executable + "JceMinerPath": "JceMiner/jce_cn_gpu_miner64.exe", + // Path to JceMiner config (can be null <- then auto configuration will be used) + "JceMinerConfig": "JceMiner/config_v7.txt", + // Extra arguments for JceMiner + "JceMinerExtraArguments": null } diff --git a/CryptonightProfitSwitcher.csproj b/CryptonightProfitSwitcher.csproj index 872d27c..d4fbabf 100644 --- a/CryptonightProfitSwitcher.csproj +++ b/CryptonightProfitSwitcher.csproj @@ -6,18 +6,23 @@ true true true - 4.5.0 + 5.0.0 Debug;Release;ReleaseLinux icon.ico - + + + + + Always + Always @@ -83,6 +88,18 @@ + + Always + + + Always + + + Always + + + Always + Always diff --git a/Enums/Miner.cs b/Enums/Miner.cs index 2a03943..689b1a6 100644 --- a/Enums/Miner.cs +++ b/Enums/Miner.cs @@ -2,6 +2,6 @@ { public enum Miner { - XmrStak, CastXmr, SRBMiner + XmrStak, CastXmr, SRBMiner, JceMiner } } \ No newline at end of file diff --git a/Enums/ProfitProvider.cs b/Enums/ProfitProvider.cs index ed86865..072e6ff 100644 --- a/Enums/ProfitProvider.cs +++ b/Enums/ProfitProvider.cs @@ -2,6 +2,6 @@ { public enum ProfitProvider { - MineCryptonightApi, NiceHashApi, MinerRocksApi, MoneroOceanApi, CryptoknightCCApi + MineCryptonightApi, NiceHashApi, MinerRocksApi, MoneroOceanApi, CryptoknightCCApi, CryptunitApi } } diff --git a/Factories/MinerFactory.cs b/Factories/MinerFactory.cs index 35ee3dc..4ec7358 100644 --- a/Factories/MinerFactory.cs +++ b/Factories/MinerFactory.cs @@ -16,6 +16,8 @@ public static IMiner GetMiner(Miner miner) return new CastXmrMiner(); case Miner.SRBMiner: return new SrbMiner(); + case Miner.JceMiner: + return new JceMiner(); default: throw new NotImplementedException("Couldn't start miner, unknown miner: " + miner); } diff --git a/Factories/PoolProfitProviderFactory.cs b/Factories/PoolProfitProviderFactory.cs index 21b93e6..c30d014 100644 --- a/Factories/PoolProfitProviderFactory.cs +++ b/Factories/PoolProfitProviderFactory.cs @@ -18,6 +18,8 @@ public static IPoolProfitProvider GetPoolProfitProvider(ProfitProvider profitPro return new MoneroOceanApi(); case ProfitProvider.CryptoknightCCApi: return new CryptoknightCcApi(); + case ProfitProvider.CryptunitApi: + return new CryptunitApi(); default: throw new NotImplementedException("Doesn't support ProfitProvider: " + profitProvider); } diff --git a/Helpers.cs b/Helpers.cs index 8d7ca79..edcb6a4 100644 --- a/Helpers.cs +++ b/Helpers.cs @@ -11,14 +11,17 @@ using System.Net; using System.Net.Http; using System.Net.Http.Headers; +using System.Net.Sockets; using System.Reflection; using System.Runtime.InteropServices; +using System.Text; using System.Threading; namespace CryptonightProfitSwitcher { internal static class Helpers { + internal static Dictionary ManualSelectionDictionary = new Dictionary { {ConsoleKey.D1, "1"}, {ConsoleKey.D2, "2"}, {ConsoleKey.D3, "3"}, @@ -32,6 +35,24 @@ internal static class Helpers {ConsoleKey.F7,"F7"}, {ConsoleKey.F8,"F8"}, {ConsoleKey.F9 ,"F9"}, {ConsoleKey.F10,"F10"}, {ConsoleKey.F11,"F11"}, {ConsoleKey.F12 ,"F12"} }; + + public static string CreateMD5(string input) + { + // Use input string to calculate MD5 hash + using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create()) + { + byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input); + byte[] hashBytes = md5.ComputeHash(inputBytes); + + // Convert the byte array to hexadecimal string + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < hashBytes.Length; i++) + { + sb.Append(hashBytes[i].ToString("X2")); + } + return sb.ToString(); + } + } internal static string ToCurrency(this double val, string currencySymbol) { var rounded = Math.Round(val, 2, MidpointRounding.AwayFromZero); @@ -44,7 +65,15 @@ internal static T GetProperty(ExpandoObject expando, string propertyName) var propertyValue = expandoDict[propertyName]; return (T)propertyValue; } - + private static readonly IPEndPoint DefaultLoopbackEndpoint = new IPEndPoint(IPAddress.Loopback, port: 0); + public static int GetAvailablePort() + { + using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) + { + socket.Bind(DefaultLoopbackEndpoint); + return ((IPEndPoint)socket.LocalEndPoint).Port; + } + } internal static string GetApplicationRoot() { var exePath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); @@ -172,7 +201,7 @@ internal static string GetJsonFromUrl(string url, Settings settings, DirectoryIn tries++; try { - string hashedFilename = url.GetHashCode() + ".json"; + string hashedFilename = CreateMD5(url) + ".json"; string savePath = Path.Combine(cacheFolder.FullName, hashedFilename); _lock.EnterWriteLock(); File.WriteAllText(savePath, responseBody); @@ -198,7 +227,7 @@ internal static string GetJsonFromUrl(string url, Settings settings, DirectoryIn Console.WriteLine("Error message: " + ex.Message); //Try to get from cache - string hashedFilename = url.GetHashCode() + ".json"; + string hashedFilename = CreateMD5(url) + ".json"; var cachedFile = cacheFolder.GetFiles(hashedFilename).First(); var cachedContent = File.ReadAllText(cachedFile.FullName); Console.WriteLine("Got data from cache."); diff --git a/JceMiner/config_heavy.txt b/JceMiner/config_heavy.txt new file mode 100644 index 0000000..c2560c2 --- /dev/null +++ b/JceMiner/config_heavy.txt @@ -0,0 +1,16 @@ + +"cpu_threads_conf" : +[ + { "cpu_architecture" : "auto", "affine_to_cpu" : 0, "use_cache" : true }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 3, "use_cache" : true }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 6, "use_cache" : true }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 9, "use_cache" : true }, +], + +"gpu_threads_conf" : +[ + { "mode" : "GPU", "worksize" : 8, "alpha" : 64, "beta" : 16, "gamma" : 4, "delta" : 4, "epsilon" : 4, "zeta" : 4, "index" : 0, "multi_hash":976 }, + { "mode" : "GPU", "worksize" : 8, "alpha" : 64, "beta" : 16, "gamma" : 4, "delta" : 4, "epsilon" : 4, "zeta" : 4, "index" : 0, "multi_hash":976 }, + { "mode" : "GPU", "worksize" : 8, "alpha" : 64, "beta" : 16, "gamma" : 4, "delta" : 4, "epsilon" : 4, "zeta" : 4, "index" : 1, "multi_hash":944 }, + { "mode" : "GPU", "worksize" : 8, "alpha" : 64, "beta" : 16, "gamma" : 4, "delta" : 4, "epsilon" : 4, "zeta" : 4, "index" : 1, "multi_hash":944 }, +] diff --git a/JceMiner/config_lite.txt b/JceMiner/config_lite.txt new file mode 100644 index 0000000..14913ae --- /dev/null +++ b/JceMiner/config_lite.txt @@ -0,0 +1,24 @@ + +"cpu_threads_conf" : +[ + { "cpu_architecture" : "auto", "affine_to_cpu" : 0, "use_cache" : true, "multi_hash":2 }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 1, "use_cache" : true, "multi_hash":1 }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 2, "use_cache" : true, "multi_hash":1 }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 3, "use_cache" : true, "multi_hash":1 }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 4, "use_cache" : true, "multi_hash":1 }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 5, "use_cache" : true, "multi_hash":1 }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 6, "use_cache" : true, "multi_hash":2 }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 7, "use_cache" : true, "multi_hash":1 }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 8, "use_cache" : true, "multi_hash":1 }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 9, "use_cache" : true, "multi_hash":1 }, + { "cpu_architecture" : "auto", "affine_to_cpu" :10, "use_cache" : true, "multi_hash":1 }, + { "cpu_architecture" : "auto", "affine_to_cpu" :11, "use_cache" : true, "multi_hash":1 }, +], + +"gpu_threads_conf" : +[ + { "mode" : "GPU", "worksize" : 16, "alpha" : 64, "beta" : 16, "gamma" : 4, "delta" : 4, "epsilon" : 4, "zeta" : 4, "index" : 0, "multi_hash":3648 }, + { "mode" : "GPU", "worksize" : 16, "alpha" : 64, "beta" : 16, "gamma" : 4, "delta" : 4, "epsilon" : 4, "zeta" : 4, "index" : 0, "multi_hash":3648 }, + { "mode" : "GPU", "worksize" : 16, "alpha" : 64, "beta" : 16, "gamma" : 4, "delta" : 4, "epsilon" : 4, "zeta" : 4, "index" : 1, "multi_hash":3488 }, + { "mode" : "GPU", "worksize" : 16, "alpha" : 64, "beta" : 16, "gamma" : 4, "delta" : 4, "epsilon" : 4, "zeta" : 4, "index" : 1, "multi_hash":3488 }, +] diff --git a/JceMiner/config_v7.txt b/JceMiner/config_v7.txt new file mode 100644 index 0000000..308ece6 --- /dev/null +++ b/JceMiner/config_v7.txt @@ -0,0 +1,19 @@ + +"cpu_threads_conf" : +[ + { "cpu_architecture" : "auto", "affine_to_cpu" : 0, "use_cache" : true }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 2, "use_cache" : true }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 4, "use_cache" : true }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 6, "use_cache" : true }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 8, "use_cache" : true }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 7, "use_cache" : true }, + { "cpu_architecture" : "auto", "affine_to_cpu" : 10, "use_cache" : true }, +], + +"gpu_threads_conf" : +[ + { "mode" : "GPU", "worksize" : 16, "alpha" : 64, "beta" : 16, "gamma" : 4, "delta" : 4, "epsilon" : 4, "zeta" : 4, "index" : 0, "multi_hash":1920 }, + { "mode" : "GPU", "worksize" : 16, "alpha" : 64, "beta" : 16, "gamma" : 4, "delta" : 4, "epsilon" : 4, "zeta" : 4, "index" : 0, "multi_hash":1920 }, + { "mode" : "GPU", "worksize" : 16, "alpha" : 64, "beta" : 16, "gamma" : 4, "delta" : 4, "epsilon" : 4, "zeta" : 4, "index" : 1, "multi_hash":1888 }, + { "mode" : "GPU", "worksize" : 16, "alpha" : 64, "beta" : 16, "gamma" : 4, "delta" : 4, "epsilon" : 4, "zeta" : 4, "index" : 1, "multi_hash":1888 }, +] diff --git a/JceMiner/jce_cn_gpu_miner64.exe b/JceMiner/jce_cn_gpu_miner64.exe new file mode 100644 index 0000000..a411cc3 Binary files /dev/null and b/JceMiner/jce_cn_gpu_miner64.exe differ diff --git a/Mineables/Mineable.cs b/Mineables/Mineable.cs index ed5c410..7192b92 100644 --- a/Mineables/Mineable.cs +++ b/Mineables/Mineable.cs @@ -37,6 +37,10 @@ public abstract class Mineable public string SRBMinerExtraArguments { get; set; } public int SRBMinerApiPort { get; set; } public bool SRBMinerUseXmrStakCPUMining { get; set; } + public string JceMinerPath { get; set; } + public string JceMinerExtraArguments { get; set; } + public string JceMinerConfig { get; set; } + public abstract string Id { get; } public bool IsEnabled() diff --git a/Miners/CastXmrMiner.cs b/Miners/CastXmrMiner.cs index 8b2d354..c5d0a7c 100644 --- a/Miners/CastXmrMiner.cs +++ b/Miners/CastXmrMiner.cs @@ -17,6 +17,7 @@ public class CastXmrMiner : IMiner Mineable _mineable = null; IMiner _cpuMiner = null; + public string Name => "Cast XMR"; public double GetCurrentHashrate(Settings settings, DirectoryInfo appRootFolder) { double gpuHashrate = 0; diff --git a/Miners/IMiner.cs b/Miners/IMiner.cs index b20d42d..d0feeea 100644 --- a/Miners/IMiner.cs +++ b/Miners/IMiner.cs @@ -9,5 +9,6 @@ public interface IMiner void StartMiner(Mineable mineable, Settings settings, string appRoot, DirectoryInfo appRootFolder); void StopMiner(); double GetCurrentHashrate(Settings settings, DirectoryInfo appRootFolder); + string Name { get; } } } diff --git a/Miners/JceMiner.cs b/Miners/JceMiner.cs new file mode 100644 index 0000000..a146b6a --- /dev/null +++ b/Miners/JceMiner.cs @@ -0,0 +1,174 @@ +using CryptonightProfitSwitcher.Enums; +using CryptonightProfitSwitcher.Mineables; +using CryptonightProfitSwitcher.Models; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Threading; + +namespace CryptonightProfitSwitcher.Miners +{ + class JceMiner : IMiner + { + Process _process = null; + Mineable _mineable = null; + private int _port; + public string Name => "JCE Miner"; + + public double GetCurrentHashrate(Settings settings, DirectoryInfo appRootFolder) + { + double gpuHashrate = 0; + try + { + var json = Helpers.GetJsonFromUrl($"http://127.0.0.1:{_port}", settings, appRootFolder, CancellationToken.None); + dynamic api = JObject.Parse(json); + + gpuHashrate = api.hashrate.total; + return gpuHashrate; + } + catch (Exception ex) + { + Console.WriteLine("Couldn't get current hashrate: " + ex.Message); + } + return 0; + } + + public void StartMiner(Mineable mineable, Settings settings, string appRoot, DirectoryInfo appRootFolder) + { + _mineable = mineable; + _process = new Process(); + string minerPath = Helpers.ResolveToFullPath(mineable.JceMinerPath, appRoot); + string minerFolderPath = Path.GetDirectoryName(minerPath); + _process.StartInfo.FileName = "cmd"; + + List userDefindedArgs = new List(); + if (!String.IsNullOrEmpty(mineable.JceMinerExtraArguments)) + { + userDefindedArgs.AddRange(mineable.JceMinerExtraArguments.Split(" ")); + } + + string args = ""; + string space = ""; + if (!userDefindedArgs.Contains("-o")) + { + args = $"{space}-o {mineable.PoolAddress}"; + space = " "; + } + if (!userDefindedArgs.Contains("-u")) + { + args += $"{space}-u {mineable.PoolWalletAddress}"; + space = " "; + } + if (!userDefindedArgs.Contains("-p")) + { + args += $"{space}-p {mineable.PoolPassword}"; + space = " "; + } + if (!userDefindedArgs.Contains("--auto")) + { + if (!userDefindedArgs.Contains("--c") && !String.IsNullOrEmpty(mineable.JceMinerConfig)) + { + string configPath = Helpers.ResolveToFullPath(mineable.JceMinerConfig, appRoot); + File.Copy(configPath, Path.Combine(minerFolderPath, "current_config.txt"), true); + args += $"{space}-c current_config.txt"; + } + else + { + args += $"{space}--auto"; + } + space = " "; + } + if (!userDefindedArgs.Contains("--any")) + { + args += $"{space}--any"; + space = " "; + } + + if (!userDefindedArgs.Contains("--variation")) + { + switch (mineable.Algorithm) + { + case Algorithm.CryptonightV7: + args += $"{space}--variation 3"; + break; + case Algorithm.CryptonightHeavy: + args += $"{space}--variation 5"; + break; + case Algorithm.CryptonightLite: + args += $"{space}--variation 4"; + break; + case Algorithm.CryptonightBittube: + args += $"{space}--variation 13"; + break; + case Algorithm.CryptonightStellite: + args += $"{space}--variation 7"; + break; + case Algorithm.CryptonightHaven: + args += $"{space}--variation 12"; + break; + case Algorithm.CryptonightMasari: + args += $"{space}--variation 11"; + break; + default: + throw new NotImplementedException($"Couldn't start JceMiner, unknown algo: {mineable.Algorithm}\n" + + "You can set --variation yourself in the extra arguments."); + } + space = " "; + } + if (!userDefindedArgs.Contains("--mport")) + { + _port = Helpers.GetAvailablePort(); + args += $"{space}--mport {_port}"; + space = " "; + } + if (!String.IsNullOrEmpty(mineable.JceMinerExtraArguments)) + { + args += space + mineable.JceMinerExtraArguments; + } + _process.StartInfo.Arguments = $"/c \"{Path.GetFileName(minerPath)} {args}\""; + _process.StartInfo.UseShellExecute = true; + _process.StartInfo.CreateNoWindow = false; + _process.StartInfo.RedirectStandardOutput = false; + _process.StartInfo.WorkingDirectory = minerFolderPath; + _process.StartInfo.WindowStyle = settings.StartMinerMinimized ? ProcessWindowStyle.Minimized : ProcessWindowStyle.Normal; + + Thread.Sleep(TimeSpan.FromSeconds(settings.MinerStartDelay)); + _process.Start(); + + + } + + public void StopMiner() + { + if (_process != null) + { + try + { + _process.CloseMainWindow(); + } + catch (Exception ex) + { + Console.WriteLine("Couldn't close miner process: " + ex.Message); + } + try + { + if (!_process.HasExited) + { + _process.Kill(); + } + } + catch (Exception ex) + { + Console.WriteLine("Couldn't kill miner process: " + ex.Message); + } + _process.Dispose(); + _process = null; + _mineable = null; + } + + } + } +} diff --git a/Miners/SrbMiner.cs b/Miners/SrbMiner.cs index 2a761ce..3967761 100644 --- a/Miners/SrbMiner.cs +++ b/Miners/SrbMiner.cs @@ -15,6 +15,7 @@ public class SrbMiner : IMiner Process _process = null; Mineable _mineable = null; IMiner _cpuMiner = null; + public string Name => "SRB Miner"; public double GetCurrentHashrate(Settings settings, DirectoryInfo appRootFolder) { diff --git a/Miners/XmrStakMiner.cs b/Miners/XmrStakMiner.cs index fb899af..b7a2773 100644 --- a/Miners/XmrStakMiner.cs +++ b/Miners/XmrStakMiner.cs @@ -17,6 +17,7 @@ public class XmrStakMiner : IMiner Process _process = null; Mineable _mineable = null; bool _cpuOnly = false; + public string Name => "XmrStak"; public XmrStakMiner(bool cpuOnly) { @@ -52,7 +53,7 @@ public void StartMiner(Mineable mineable, Settings settings, string appRoot, Dir string xmrPath = Helpers.ResolveToFullPath(mineable.XmrStakPath, appRoot); string xmrFolderPath = Path.GetDirectoryName(xmrPath); var xmrDirectory = new DirectoryInfo(xmrFolderPath); - _process.StartInfo.FileName = xmrPath; + _process.StartInfo.FileName = "cmd"; if (Helpers.IsLinux()) { _process.StartInfo.FileName = "x-terminal-emulator"; @@ -108,11 +109,14 @@ public void StartMiner(Mineable mineable, Settings settings, string appRoot, Dir args += " --nvidia current_nvidia.txt"; } - _process.StartInfo.Arguments = args; + _process.StartInfo.Arguments = $"/c \"{"set GPU_FORCE_64BIT_PTR=1 & set GPU_MAX_HEAP_SIZE=100 & set GPU_MAX_ALLOC_PERCENT=100 & set GPU_SINGLE_ALLOC_PERCENT=100 & " + Path.GetFileName(xmrPath)} {args}\""; + if (Helpers.IsLinux()) { _process.StartInfo.Arguments = $"-e \"'{xmrPath}' {args}\""; } + + _process.StartInfo.UseShellExecute = true; _process.StartInfo.CreateNoWindow = false; _process.StartInfo.RedirectStandardOutput = false; diff --git a/Models/MineableRewardResult.cs b/Models/MineableRewardResult.cs new file mode 100644 index 0000000..e430106 --- /dev/null +++ b/Models/MineableRewardResult.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CryptonightProfitSwitcher.Models +{ + public class MineableRewardResult + { + public MineableReward Result { get; set; } + public MineableReward Current { get; set; } + + public MineableRewardResult(MineableReward result, MineableReward current) + { + Result = result; + Current = current; + } + } +} diff --git a/Models/Settings.cs b/Models/Settings.cs index 532d1cb..ff75232 100644 --- a/Models/Settings.cs +++ b/Models/Settings.cs @@ -13,17 +13,18 @@ public class Settings public string PoolProfitProviders { get; set; } public int MinerStartDelay { get; set; } public int ProfitSwitchCooldown { get; set; } + public double ProfitSwitchThreshold { get; set; } public bool StartMinerMinimized { get; set; } public int ProfitCheckInterval { get; set; } public int DisplayUpdateInterval { get; set; } public string ResetScript { get; set; } public bool EnableCaching { get; set; } + public bool EnableLogging { get; set; } public bool EnableWatchdog { get; set; } public int WatchdogDelay { get; set; } public double WatchdogCriticalThreshold { get; set; } public int WatchdogInterval { get; set; } public int WatchdogAllowedOversteps { get; set; } - [Obsolete("CryptonightBittubeHashrate is deprecated, use CryptonightLiteHashrate or the override in Mineable.")] public int CryptonightBittubeHashrate { get; set; } diff --git a/NicehashAlgorithms/CryptonightHeavy.json b/NicehashAlgorithms/CryptonightHeavy.json index d4310f4..041d376 100644 --- a/NicehashAlgorithms/CryptonightHeavy.json +++ b/NicehashAlgorithms/CryptonightHeavy.json @@ -7,7 +7,7 @@ "ApiId": 31, // Mining algorithm of coin, can be CryptonightV7, CryptonightHeavy, CryptonightLite, CryptonightBittube, CryptonightStellite, CryptonightHaven or CryptonightMasari "Algorithm": "CryptonightHeavy", - // Used Miner, can be XmrStak, CastXmr or SRBMiner (Recommended: XmrStak) + // Used Miner, can be XmrStak, CastXmr, SRBMiner or JceMiner (Recommended: XmrStak) "Miner": "XmrStak", // Path to script that runs before the miner starts, can be null. // For example:: Path to batch file that sets specific OverdriveN settings for this algorithm @@ -75,7 +75,16 @@ // Extra arguments that will be passed over to SRBMiner, can be a string or null "SRBMinerExtraArguments": null, // Set if you want to also start Xmr-Stak for CPU Mining - "SRBMinerUseXmrStakCPUMining": true + "SRBMinerUseXmrStakCPUMining": true, + + /* JCEMINER CONFIGURATION - NEEDED IF MINER IS JCEMINER */ + + // Path to JceMiner executable + "JceMinerPath": "JceMiner/jce_cn_gpu_miner64.exe", + // Path to JceMiner config (can be null <- then auto configuration will be used) + "JceMinerConfig": "JceMiner/config_heavy.txt", + // Extra arguments for JceMiner + "JceMinerExtraArguments": null } diff --git a/NicehashAlgorithms/CryptonightV7.json b/NicehashAlgorithms/CryptonightV7.json index 617200f..92a577c 100644 --- a/NicehashAlgorithms/CryptonightV7.json +++ b/NicehashAlgorithms/CryptonightV7.json @@ -7,7 +7,7 @@ "ApiId": 30, // Mining algorithm of coin, can be CryptonightV7, CryptonightHeavy, CryptonightLite, CryptonightBittube, CryptonightStellite, CryptonightHaven or CryptonightMasari "Algorithm": "CryptonightV7", - // Used Miner, can be XmrStak, CastXmr or SRBMiner (Recommended: XmrStak) + // Used Miner, can be XmrStak, CastXmr, SRBMiner or JceMiner (Recommended: XmrStak) "Miner": "XmrStak", // Path to script that runs before the miner starts, can be null. // For example:: Path to batch file that sets specific OverdriveN settings for this algorithm @@ -74,6 +74,15 @@ // Extra arguments that will be passed over to SRBMiner, can be a string or null "SRBMinerExtraArguments": null, // Set if you want to also start Xmr-Stak for CPU Mining - "SRBMinerUseXmrStakCPUMining": true + "SRBMinerUseXmrStakCPUMining": true, + + /* JCEMINER CONFIGURATION - NEEDED IF MINER IS JCEMINER */ + + // Path to JceMiner executable + "JceMinerPath": "JceMiner/jce_cn_gpu_miner64.exe", + // Path to JceMiner config (can be null <- then auto configuration will be used) + "JceMinerConfig": "JceMiner/config_v7.txt", + // Extra arguments for JceMiner + "JceMinerExtraArguments": null } diff --git a/ProfitPoviders/CryptunitApi.cs b/ProfitPoviders/CryptunitApi.cs new file mode 100644 index 0000000..063b1a7 --- /dev/null +++ b/ProfitPoviders/CryptunitApi.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using CryptonightProfitSwitcher.Enums; +using CryptonightProfitSwitcher.Mineables; +using CryptonightProfitSwitcher.Models; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace CryptonightProfitSwitcher.ProfitPoviders +{ + class CryptunitApi : IPoolProfitProvider + { + public Dictionary GetProfits(DirectoryInfo appRootFolder, Settings settings, IList coins, CancellationToken ct) + { + var poolProfitsDictionary = new Dictionary(); + try + { + var profitsLiveJson = Helpers.GetJsonFromUrl("https://www.cryptunit.com/api/earnings/?hashrate=10000&device=GPU&dataavg=1h&volumefilter=&algofilter=", settings, appRootFolder, ct); + var profitsDayJson = Helpers.GetJsonFromUrl("https://www.cryptunit.com/api/earnings/?hashrate=10000&device=GPU&dataavg=24h&volumefilter=&algofilter=", settings, appRootFolder, ct); + + dynamic profitsLive = JsonConvert.DeserializeObject(profitsLiveJson); + dynamic profitsDay = JsonConvert.DeserializeObject(profitsDayJson); + + + foreach (dynamic rewardLive in profitsLive[0].coins) + { + string tickerSymbol = rewardLive.coin_ticker; + //Adjust profits based on user defined hashrate + Coin matchedCoin = coins.FirstOrDefault(c => c.TickerSymbol == tickerSymbol); + + if (matchedCoin != null) + { + double hashrate = rewardLive.hashrate_auto; + double rewardUsdLive = rewardLive.reward_day_usd; + double rewardCoinsLive = rewardLive.reward_day_coins; + foreach (dynamic rewardDay in profitsDay[0].coins) + { + if (rewardDay.coin_ticker == tickerSymbol) + { + double rewardUsdDay = rewardDay.reward_day_usd; + double rewardCoinsDay = rewardDay.reward_day_coins; + ProfitTimeframe timeFrame = matchedCoin.OverrideProfitTimeframe.HasValue ? matchedCoin.OverrideProfitTimeframe.Value : settings.ProfitTimeframe; + rewardUsdLive = (rewardUsdLive / hashrate) * matchedCoin.GetExpectedHashrate(settings); + rewardCoinsLive = (rewardCoinsLive / hashrate) * matchedCoin.GetExpectedHashrate(settings); + rewardUsdDay = (rewardUsdDay / hashrate) * matchedCoin.GetExpectedHashrate(settings); + rewardCoinsDay = (rewardCoinsDay / hashrate) * matchedCoin.GetExpectedHashrate(settings); + poolProfitsDictionary[tickerSymbol] = new Profit(rewardUsdLive, rewardUsdDay, rewardCoinsLive, rewardCoinsDay, ProfitProvider.CryptunitApi, timeFrame); + Console.WriteLine($"Got profit data for {tickerSymbol} from CryptunitAPI"); + } + } + } + } + } + catch (Exception ex) + { + Console.WriteLine("Failed to get profits data from Cryptunit Api: " + ex.Message); + } + return poolProfitsDictionary; + } + } +} diff --git a/ProfitPoviders/MinerRocksApi.cs b/ProfitPoviders/MinerRocksApi.cs index d7688d4..81490e5 100644 --- a/ProfitPoviders/MinerRocksApi.cs +++ b/ProfitPoviders/MinerRocksApi.cs @@ -88,8 +88,6 @@ private string GetApiUrl(Coin coin) return "https://masari.miner.rocks/api/stats"; case "XMR": return "https://monero.miner.rocks/api/stats"; - case "XMV": - return "https://monerov.miner.rocks/api/stats"; case "XTL": return "https://stellite.miner.rocks/api/stats"; case "LOKI": @@ -104,8 +102,10 @@ private string GetApiUrl(Coin coin) return "https://aeon.miner.rocks/api/stats"; case "TUBE": return "https://bittube.miner.rocks/api/stats"; + case "QRL": + return "https://qrl.miner.rocks/api/stats"; } - return null; + return $"https://{coin.TickerSymbol.ToLowerInvariant()}.miner.rocks/api/stats"; } } } diff --git a/ProfitSwitchingStrategies/IProfitSwitchingStrategy.cs b/ProfitSwitchingStrategies/IProfitSwitchingStrategy.cs index 9464bdd..9ff6d42 100644 --- a/ProfitSwitchingStrategies/IProfitSwitchingStrategy.cs +++ b/ProfitSwitchingStrategies/IProfitSwitchingStrategy.cs @@ -7,9 +7,9 @@ namespace CryptonightProfitSwitcher.ProfitSwitchingStrategies { public interface IProfitSwitchingStrategy { - MineableReward GetBestPoolminedCoin(IList coins, Dictionary> poolProfitsDictionary, Settings settings); - MineableReward GetBestNicehashAlgorithm(IList nicehashAlgorithms, Dictionary nicehashProfitsDictionary, Settings settings); - MineableReward GetBestMineable(MineableReward bestPoolminedCoin, MineableReward bestNicehashAlgorithm); + MineableRewardResult GetBestPoolminedCoin(IList coins, Mineable currentMineable, Dictionary> poolProfitsDictionary, Settings settings); + MineableRewardResult GetBestNicehashAlgorithm(IList nicehashAlgorithms,Mineable currentMineable, Dictionary nicehashProfitsDictionary, Settings settings); + MineableReward GetBestMineable(MineableReward bestPoolminedCoin, MineableReward bestNicehashAlgorithm, MineableReward currentReward, Settings settings); double GetReward(Profit profit, Mineable mineable, ProfitTimeframe timeframe); } } diff --git a/ProfitSwitchingStrategies/MaximizeCoinsStrategy.cs b/ProfitSwitchingStrategies/MaximizeCoinsStrategy.cs index 543f086..3b06545 100644 --- a/ProfitSwitchingStrategies/MaximizeCoinsStrategy.cs +++ b/ProfitSwitchingStrategies/MaximizeCoinsStrategy.cs @@ -9,8 +9,9 @@ namespace CryptonightProfitSwitcher.ProfitSwitchingStrategies { public class MaximizeCoinsStrategy : IProfitSwitchingStrategy { - public MineableReward GetBestPoolminedCoin(IList coins, Dictionary> poolProfitsDictionary, Settings settings) + public MineableRewardResult GetBestPoolminedCoin(IList coins, Mineable currentMineable, Dictionary> poolProfitsDictionary, Settings settings) { + MineableReward currentReward = null; Coin bestPoolminedCoin = null; double bestPoolminedCoinProfit = 0; foreach (var coin in coins.Where(c => c.IsEnabled())) @@ -18,26 +19,38 @@ public MineableReward GetBestPoolminedCoin(IList coins, Dictionary bestPoolminedCoinProfit) { bestPoolminedCoinProfit = calcProfit; bestPoolminedCoin = coin; } } - return new MineableReward(bestPoolminedCoin, bestPoolminedCoinProfit); + return new MineableRewardResult(new MineableReward(bestPoolminedCoin, bestPoolminedCoinProfit), currentReward); } - public MineableReward GetBestNicehashAlgorithm(IList nicehashAlgorithms, Dictionary nicehashProfitsDictionary, Settings settings) + public MineableRewardResult GetBestNicehashAlgorithm(IList nicehashAlgorithms, Mineable currentMineable, Dictionary nicehashProfitsDictionary, Settings settings) { Console.WriteLine("This ProfitSwitchingStrategy is incompatible with NiceHash algorithms!"); return null; } - public MineableReward GetBestMineable(MineableReward bestPoolminedCoin, MineableReward bestNicehashAlgorithm) + public MineableReward GetBestMineable(MineableReward bestPoolminedCoin, MineableReward bestNicehashAlgorithm, MineableReward currentReward, Settings settings) { if (bestPoolminedCoin.Mineable != null) { Console.WriteLine($"Determined best mining method: Mine {bestPoolminedCoin.Mineable.DisplayName} in a pool with relative factor {bestPoolminedCoin.Reward}."); + if (currentReward != null && settings.ProfitSwitchThreshold > 0 && currentReward.Mineable.Id != bestPoolminedCoin.Mineable.Id) + { + if (currentReward.Reward * (1 + settings.ProfitSwitchThreshold) > bestPoolminedCoin.Reward) + { + Console.WriteLine($"But will stay mining {currentReward.Mineable.DisplayName} because of the profit switch threshold."); + return currentReward; + } + } return bestPoolminedCoin; } else diff --git a/ProfitSwitchingStrategies/MaximizeFiatStrategy.cs b/ProfitSwitchingStrategies/MaximizeFiatStrategy.cs index 88fab21..57086f9 100644 --- a/ProfitSwitchingStrategies/MaximizeFiatStrategy.cs +++ b/ProfitSwitchingStrategies/MaximizeFiatStrategy.cs @@ -9,8 +9,9 @@ namespace CryptonightProfitSwitcher.ProfitSwitchingStrategies { public class MaximizeFiatStrategy : IProfitSwitchingStrategy { - public MineableReward GetBestPoolminedCoin(IList coins, Dictionary> poolProfitsDictionary, Settings settings) + public MineableRewardResult GetBestPoolminedCoin(IList coins, Mineable currentMineable, Dictionary> poolProfitsDictionary, Settings settings) { + MineableReward currentReward = null; Coin bestPoolminedCoin = null; double bestPoolminedCoinProfit = 0; foreach (var coin in coins.Where(c => c.IsEnabled())) @@ -18,17 +19,22 @@ public MineableReward GetBestPoolminedCoin(IList coins, Dictionary bestPoolminedCoinProfit) { bestPoolminedCoinProfit = calcProfit; bestPoolminedCoin = coin; } } - return new MineableReward(bestPoolminedCoin, bestPoolminedCoinProfit); + return new MineableRewardResult(new MineableReward(bestPoolminedCoin, bestPoolminedCoinProfit), currentReward); } - public MineableReward GetBestNicehashAlgorithm(IList nicehashAlgorithms, Dictionary nicehashProfitsDictionary, Settings settings) + public MineableRewardResult GetBestNicehashAlgorithm(IList nicehashAlgorithms, Mineable currentMineable, Dictionary nicehashProfitsDictionary, Settings settings) { + MineableReward currentReward = null; NicehashAlgorithm bestNicehashAlgorithm = null; double bestNicehashAlgorithmProfit = 0; foreach (var nicehashAlgorithm in nicehashAlgorithms.Where(na => na.IsEnabled())) @@ -48,25 +54,45 @@ public MineableReward GetBestNicehashAlgorithm(IList nicehash } } double calcProfit = GetReward(profit, nicehashAlgorithm, settings.ProfitTimeframe) * preferFactor; + if (currentMineable != null && nicehashAlgorithm.Id == currentMineable.Id) + { + currentReward = new MineableReward(currentMineable, calcProfit); + } if (bestNicehashAlgorithm == null || calcProfit > bestNicehashAlgorithmProfit) { bestNicehashAlgorithmProfit = calcProfit; bestNicehashAlgorithm = nicehashAlgorithm; } } - return new MineableReward(bestNicehashAlgorithm, bestNicehashAlgorithmProfit); + return new MineableRewardResult(new MineableReward(bestNicehashAlgorithm, bestNicehashAlgorithmProfit), currentReward); } - public MineableReward GetBestMineable(MineableReward bestPoolminedCoin, MineableReward bestNicehashAlgorithm) + public MineableReward GetBestMineable(MineableReward bestPoolminedCoin, MineableReward bestNicehashAlgorithm, MineableReward currentReward, Settings settings) { if (bestPoolminedCoin.Mineable != null && bestPoolminedCoin.Reward > bestNicehashAlgorithm.Reward) { Console.WriteLine($"Determined best mining method: Mine {bestPoolminedCoin.Mineable.DisplayName} in a pool at {Helpers.ToCurrency(bestPoolminedCoin.Reward, "$")} per day."); + if (currentReward != null && settings.ProfitSwitchThreshold > 0 && currentReward.Mineable.Id != bestPoolminedCoin.Mineable.Id) + { + if (currentReward.Reward * (1 + settings.ProfitSwitchThreshold) > bestPoolminedCoin.Reward) + { + Console.WriteLine($"But will stay mining {currentReward.Mineable.DisplayName} because of the profit switch threshold."); + return currentReward; + } + } return bestPoolminedCoin; } else if (bestNicehashAlgorithm.Mineable != null) { Console.WriteLine($"Determined best mining method: Provide hash power for {bestNicehashAlgorithm.Mineable.DisplayName} on NiceHash at {Helpers.ToCurrency(bestNicehashAlgorithm.Reward, "$")} per day."); + if (currentReward != null && settings.ProfitSwitchThreshold > 0 && currentReward.Mineable.Id != bestNicehashAlgorithm.Mineable.Id) + { + if (currentReward.Reward * (1 + settings.ProfitSwitchThreshold) > bestNicehashAlgorithm.Reward) + { + Console.WriteLine($"But will stay mining {currentReward.Mineable.DisplayName} because of the profit switch threshold."); + return currentReward; + } + } return bestNicehashAlgorithm; } else diff --git a/ProfitSwitchingStrategies/WeightedCoinsPriceStrategy.cs b/ProfitSwitchingStrategies/WeightedCoinsPriceStrategy.cs index 34c0996..9136ec3 100644 --- a/ProfitSwitchingStrategies/WeightedCoinsPriceStrategy.cs +++ b/ProfitSwitchingStrategies/WeightedCoinsPriceStrategy.cs @@ -9,8 +9,9 @@ namespace CryptonightProfitSwitcher.ProfitSwitchingStrategies { public class WeightedCoinsPriceStrategy : IProfitSwitchingStrategy { - public MineableReward GetBestPoolminedCoin(IList coins, Dictionary> poolProfitsDictionary, Settings settings) + public MineableRewardResult GetBestPoolminedCoin(IList coins, Mineable currentMineable, Dictionary> poolProfitsDictionary, Settings settings) { + MineableReward currentReward = null; Coin bestPoolminedCoin = null; double bestPoolminedCoinProfit = 0; foreach (var coin in coins.Where(c => c.IsEnabled())) @@ -18,31 +19,51 @@ public MineableReward GetBestPoolminedCoin(IList coins, Dictionary bestPoolminedCoinProfit) { bestPoolminedCoinProfit = calcProfit; bestPoolminedCoin = coin; } } - return new MineableReward(bestPoolminedCoin, bestPoolminedCoinProfit); + return new MineableRewardResult(new MineableReward(bestPoolminedCoin, bestPoolminedCoinProfit), currentReward); } - public MineableReward GetBestNicehashAlgorithm(IList nicehashAlgorithms, Dictionary nicehashProfitsDictionary, Settings settings) + public MineableRewardResult GetBestNicehashAlgorithm(IList nicehashAlgorithms, Mineable currentMineable, Dictionary nicehashProfitsDictionary, Settings settings) { var maximizeFiatStrategy = new MaximizeFiatStrategy(); - return maximizeFiatStrategy.GetBestNicehashAlgorithm(nicehashAlgorithms, nicehashProfitsDictionary, settings); + return maximizeFiatStrategy.GetBestNicehashAlgorithm(nicehashAlgorithms,currentMineable, nicehashProfitsDictionary, settings); } - public MineableReward GetBestMineable(MineableReward bestPoolminedCoin, MineableReward bestNicehashAlgorithm) + public MineableReward GetBestMineable(MineableReward bestPoolminedCoin, MineableReward bestNicehashAlgorithm, MineableReward currentReward, Settings settings) { if (bestPoolminedCoin.Mineable != null && bestPoolminedCoin.Reward > bestNicehashAlgorithm.Reward) { Console.WriteLine($"Determined best mining method: Mine {bestPoolminedCoin.Mineable.DisplayName} in a pool at {Helpers.ToCurrency(bestPoolminedCoin.Reward, "$")} per day."); + if (currentReward != null && settings.ProfitSwitchThreshold > 0 && currentReward.Mineable.Id != bestPoolminedCoin.Mineable.Id) + { + if (currentReward.Reward * (1 + settings.ProfitSwitchThreshold) > bestPoolminedCoin.Reward) + { + Console.WriteLine($"But will stay mining {currentReward.Mineable.DisplayName} because of the profit switch threshold."); + return currentReward; + } + } return bestPoolminedCoin; } else if (bestNicehashAlgorithm.Mineable != null) { Console.WriteLine($"Determined best mining method: Provide hash power for {bestNicehashAlgorithm.Mineable.DisplayName} on NiceHash at {Helpers.ToCurrency(bestNicehashAlgorithm.Reward, "$")} per day."); + if (currentReward != null && settings.ProfitSwitchThreshold > 0 && currentReward.Mineable.Id != bestNicehashAlgorithm.Mineable.Id) + { + if (currentReward.Reward * (1 + settings.ProfitSwitchThreshold) > bestNicehashAlgorithm.Reward) + { + Console.WriteLine($"But will stay mining {currentReward.Mineable.DisplayName} because of the profit switch threshold."); + return currentReward; + } + } return bestNicehashAlgorithm; } else diff --git a/Program.cs b/Program.cs index ce74345..300fef0 100644 --- a/Program.cs +++ b/Program.cs @@ -14,12 +14,13 @@ using System.Threading; using System.Threading.Tasks; using CryptonightProfitSwitcher.ProfitSwitchingStrategies; +using Serilog; namespace CryptonightProfitSwitcher { class Program { - const int VERSION = 7; + const int VERSION = 8; static IMiner _currentMiner = null; static Mineable _currentMineable = null; @@ -34,20 +35,41 @@ class Program static CancellationTokenSource _profitSwitcherTaskCts = null; static Task _profitSwitcherTask; static DateTimeOffset _lastProfitSwitch = DateTimeOffset.MinValue; - static void Main(string[] args) { + //Get app root + var appFolderPath = Helpers.GetApplicationRoot(); + var appFolder = new DirectoryInfo(appFolderPath); + + //Initalize logging file + string logPath = Path.Combine(appFolderPath, "current_log.txt"); + try + { + var logFile = new FileInfo(logPath); + if (logFile.Exists) + { + string oldlogPath = Path.Combine(appFolderPath, "previous_log.txt"); + if (File.Exists(oldlogPath)) + { + File.Delete(oldlogPath); + } + logFile.MoveTo(oldlogPath); + } + } + catch (Exception e) + { + Console.WriteLine("Couldn't initalize log file: " + e.Message); + } + while (!_requestQuit) { _mainResetCts = new CancellationTokenSource(); //Welcome ResetConsole(); - //Get app root - var appFolderPath = Helpers.GetApplicationRoot(); - var appFolder = new DirectoryInfo(appFolderPath); - //Initalize coins + Console.WriteLine("Initalize coins"); + var coinsFolder = appFolder.GetDirectories("Coins").First(); var coins = new List(); foreach (var coinFile in coinsFolder.GetFiles().Where(f => f.Extension == ".json")) @@ -59,6 +81,8 @@ static void Main(string[] args) } //Initalize Nicehash algorithms + Console.WriteLine("Initalize Nicehash algorithms"); + var nicehashAlgorithmsFolder = appFolder.GetDirectories("NicehashAlgorithms").First(); var nicehashAlgorithms = new List(); foreach (var nicehashAlgorithmFile in nicehashAlgorithmsFolder.GetFiles().Where(f => f.Extension == ".json")) @@ -70,17 +94,38 @@ static void Main(string[] args) } //Initalize settings + Console.WriteLine("Initalize settings"); + var settingsFile = appFolder.GetFiles("Settings.json").First(); var settingsJson = File.ReadAllText(settingsFile.FullName); var settings = JsonConvert.DeserializeObject(settingsJson); Console.WriteLine("Initalized settings."); + //Initalize logging + if (settings.EnableLogging) + { + Log.Logger = new LoggerConfiguration() + .WriteTo.Console() + .WriteTo.File(logPath) + .CreateLogger(); + } + else + { + Log.Logger = new LoggerConfiguration() + .WriteTo.Console() + .CreateLogger(); + } + //Start profit switching algorithm + Log.Information("Start profit switching algorithm"); + _profitSwitcherTaskCts?.Cancel(); _profitSwitcherTaskCts = new CancellationTokenSource(); _profitSwitcherTask = ProfitSwitcherTask(appFolderPath, appFolder, settings, coins, nicehashAlgorithms, _profitSwitcherTaskCts.Token); //Start key presses task + Log.Information("Start key presses task"); + _keyPressesCts?.Cancel(); _keyPressesCts = new CancellationTokenSource(); var keyPressesTask = KeypressesTask(appFolderPath, appFolder, settings, coins, nicehashAlgorithms, _keyPressesCts.Token); @@ -88,25 +133,28 @@ static void Main(string[] args) //Check for updates try { + Log.Information("Check for updates"); + var versionText = Helpers.GetJsonFromUrl("https://raw.githubusercontent.com/cryptoprofitswitcher/CryptonightProfitSwitcher/master/version.txt", settings, appFolder, CancellationToken.None); int remoteVersion = Int32.Parse(versionText); if (remoteVersion > VERSION) { _newVersionAvailable = true; - Console.WriteLine("New update available!"); + Log.Information("New update available!"); + } else { - Console.WriteLine("Your version is up to date."); + Log.Information("Your version is up to date."); } } catch (Exception ex) { - Console.WriteLine("Couldn't check for updates: " + ex.Message); + Log.Information("Couldn't check for updates: " + ex.Message); } //Wait until reset _mainResetCts.Token.WaitHandle.WaitOne(); - Console.WriteLine("Reset app"); + Log.Information("Reset app"); } } @@ -181,11 +229,15 @@ static Task ProfitSwitcherTask(string appFolderPath, DirectoryInfo appRootFolder IProfitSwitchingStrategy profitSwitchingStrategy = ProfitSwitchingStrategyFactory.GetProfitSwitchingStrategy(settings.ProfitSwitchingStrategy); + MineableReward currentReward = null; + // Get best pool mined coin MineableReward bestPoolminedCoin = null; if (!token.IsCancellationRequested) { - bestPoolminedCoin = profitSwitchingStrategy.GetBestPoolminedCoin(coins, poolProfitsDictionary, settings); + var result = profitSwitchingStrategy.GetBestPoolminedCoin(coins,_currentMineable, poolProfitsDictionary, settings); + bestPoolminedCoin = result?.Result; + if (currentReward == null) currentReward = result?.Current; if (bestPoolminedCoin?.Mineable != null) { Console.WriteLine("Got best pool mined coin: " + bestPoolminedCoin.Mineable.DisplayName); @@ -207,7 +259,9 @@ static Task ProfitSwitcherTask(string appFolderPath, DirectoryInfo appRootFolder MineableReward bestNicehashAlgorithm = null; if (!token.IsCancellationRequested && nicehashProfitsDictionary != null) { - bestNicehashAlgorithm = profitSwitchingStrategy.GetBestNicehashAlgorithm(nicehashAlgorithms, nicehashProfitsDictionary, settings); + var result = profitSwitchingStrategy.GetBestNicehashAlgorithm(nicehashAlgorithms,_currentMineable, nicehashProfitsDictionary, settings); + bestNicehashAlgorithm = result?.Result; + if (currentReward == null) currentReward = result?.Current; if (bestNicehashAlgorithm?.Mineable != null) { Console.WriteLine("Got best nicehash algorithm: " + bestNicehashAlgorithm.Mineable.DisplayName); @@ -218,6 +272,7 @@ static Task ProfitSwitcherTask(string appFolderPath, DirectoryInfo appRootFolder } } + //Print table if (!token.IsCancellationRequested && nicehashProfitsDictionary != null) { @@ -235,7 +290,7 @@ static Task ProfitSwitcherTask(string appFolderPath, DirectoryInfo appRootFolder } else { - bestOverallMineable = profitSwitchingStrategy.GetBestMineable(bestPoolminedCoin, bestNicehashAlgorithm)?.Mineable; + bestOverallMineable = profitSwitchingStrategy.GetBestMineable(bestPoolminedCoin, bestNicehashAlgorithm, currentReward, settings)?.Mineable; } if (bestOverallMineable != null) { @@ -247,7 +302,7 @@ static Task ProfitSwitcherTask(string appFolderPath, DirectoryInfo appRootFolder } else { - Console.WriteLine("Couldn't determine best mining method."); + Log.Information("Couldn't determine best mining method."); } } @@ -257,7 +312,7 @@ static Task ProfitSwitcherTask(string appFolderPath, DirectoryInfo appRootFolder { if (settings.ProfitCheckInterval > 0) { - Task.Delay(TimeSpan.FromSeconds(settings.ProfitCheckInterval), token).Wait(); + Task.Delay(TimeSpan.FromSeconds(settings.ProfitCheckInterval), token).Wait(token); } else { @@ -269,19 +324,19 @@ static Task ProfitSwitcherTask(string appFolderPath, DirectoryInfo appRootFolder } catch (TaskCanceledException) { - Console.WriteLine("Cancelled profit task."); + Log.Information("Cancelled profit task."); statusCts.Cancel(); return; } catch (AggregateException) { - Console.WriteLine("Cancelled profit task."); + Log.Information("Cancelled profit task 2."); statusCts.Cancel(); return; } catch (Exception ex) { - Console.WriteLine("Profit switcher task failed: " + ex.Message); + Log.Error("Profit switcher task failed: " + ex.Message); statusCts.Cancel(); } } @@ -385,7 +440,7 @@ static Task StatusUpdaterTask(DateTimeOffset estReset, Settings settings, Direct if (currentUsdReward > 0) { Console.ForegroundColor = ConsoleColor.Yellow; - Console.Write(Helpers.ToCurrency(currentUsdReward, "$")); + Console.Write(currentUsdReward.ToCurrency("$")); Console.ResetColor(); } if (currentCoinReward > 0) @@ -416,7 +471,7 @@ static Task StatusUpdaterTask(DateTimeOffset estReset, Settings settings, Direct { Console.Write(" ("); Console.ForegroundColor = ConsoleColor.Yellow; - Console.Write(Helpers.ToCurrency(currentUsdReward, "$")); + Console.Write(currentUsdReward.ToCurrency("$")); Console.ResetColor(); Console.WriteLine(" per day)"); } @@ -490,22 +545,22 @@ static Task StatusUpdaterTask(DateTimeOffset estReset, Settings settings, Direct { Console.WriteLine(" Won't refresh automatically."); } - Task.Delay(TimeSpan.FromSeconds(settings.DisplayUpdateInterval), token).Wait(); + Task.Delay(TimeSpan.FromSeconds(settings.DisplayUpdateInterval), token).Wait(token); } } catch (TaskCanceledException) { - Console.WriteLine(" Cancelled status task."); + Log.Information(" Cancelled status task."); return; } catch (AggregateException) { - Console.WriteLine(" Cancelled status task."); + Log.Information(" Cancelled status task 2."); return; } catch (Exception ex) { - Console.WriteLine(" Status task failed: " + ex.Message); + Log.Error(" Status task failed: " + ex.Message); } }, token); } @@ -536,26 +591,26 @@ static Task WatchdogTask(Settings settings, string appFolderPath, DirectoryInfo if (_watchdogOvershots > settings.WatchdogAllowedOversteps) { - Console.WriteLine("Watchdog: Too many overshots -> Requesting reset"); + Log.Information("Watchdog: Too many overshots -> Requesting reset"); ResetApp(settings, appFolderPath, true); } } - Task.Delay(TimeSpan.FromSeconds(settings.WatchdogInterval), token).Wait(); + Task.Delay(TimeSpan.FromSeconds(settings.WatchdogInterval), token).Wait(token); } } catch (TaskCanceledException) { - Console.WriteLine("Cancelled watchdog task."); + Log.Information("Cancelled watchdog task."); return; } catch (AggregateException) { - Console.WriteLine("Cancelled watchdog task."); + Log.Information("Cancelled watchdog task 2."); return; } catch (Exception ex) { - Console.WriteLine("Watchdog task failed: " + ex.Message); + Log.Error("Watchdog task failed: " + ex.Message); } }, token); } @@ -613,6 +668,7 @@ static Task KeypressesTask(string appFolderPath, DirectoryInfo appFolder, Settin if (_manualSelectedMineable != coins[keyIndex]) { _manualSelectedMineable = coins[keyIndex]; + _lastProfitSwitch = DateTimeOffset.MinValue; RestartProfitTask(appFolderPath, appFolder, settings, coins, nicehashAlgorithms); } } @@ -624,6 +680,7 @@ static Task KeypressesTask(string appFolderPath, DirectoryInfo appFolder, Settin if (_manualSelectedMineable != nicehashAlgorithms[nicehashIndex]) { _manualSelectedMineable = nicehashAlgorithms[nicehashIndex]; + _lastProfitSwitch = DateTimeOffset.MinValue; RestartProfitTask(appFolderPath, appFolder, settings, coins, nicehashAlgorithms); } } @@ -635,19 +692,19 @@ static Task KeypressesTask(string appFolderPath, DirectoryInfo appFolder, Settin } catch (TaskCanceledException) { - Console.WriteLine("Cancelled key presses task."); + Log.Information("Cancelled key presses task."); //ResetApp(settings,appFolderPath); return; } catch (AggregateException) { - Console.WriteLine("Cancelled key presses task."); + Log.Information("Cancelled key presses task 2."); //ResetApp(settings, appFolderPath); return; } catch (Exception ex) { - Console.WriteLine("Key presses task failed: " + ex.Message); + Log.Error("Key presses task failed: " + ex.Message); } }, token); } @@ -766,7 +823,7 @@ static void PrintProfitTable(List coins, Dictionary auto intensity, or value from 1-300 */ "intensity" : 0, diff --git a/SRBMiner/config_fast.txt b/SRBMiner/config_fast.txt index cbc1666..103a55f 100644 --- a/SRBMiner/config_fast.txt +++ b/SRBMiner/config_fast.txt @@ -23,6 +23,6 @@ "gpu_conf" : [ { "id" : 0, "intensity" : 120, "worksize" : 16, "threads" : 2}, - { "id" : 1, "intensity" : 112, "worksize" : 16, "threads" : 2}, + { "id" : 1, "intensity" : 96, "worksize" : 16, "threads" : 2}, ] } \ No newline at end of file diff --git a/SRBMiner/config_stellite.txt b/SRBMiner/config_stellite.txt index 89ae850..6b19fa6 100644 --- a/SRBMiner/config_stellite.txt +++ b/SRBMiner/config_stellite.txt @@ -23,6 +23,6 @@ "gpu_conf" : [ { "id" : 0, "intensity" : 120, "worksize" : 16, "threads" : 2}, - { "id" : 1, "intensity" : 112, "worksize" : 16, "threads" : 2}, + { "id" : 1, "intensity" : 96, "worksize" : 16, "threads" : 2}, ] } \ No newline at end of file diff --git a/SRBMiner/config_v7.txt b/SRBMiner/config_v7.txt index 8e76f5c..0053bed 100644 --- a/SRBMiner/config_v7.txt +++ b/SRBMiner/config_v7.txt @@ -22,7 +22,7 @@ "gpu_conf" : [ - { "id" : 0, "intensity" : 112, "worksize" : 16, "threads" : 2}, - { "id" : 1, "intensity" : 120, "worksize" : 16, "threads" : 2}, + { "id" : 0, "intensity" : 120, "worksize" : 16, "threads" : 2}, + { "id" : 1, "intensity" : 96, "worksize" : 16, "threads" : 2}, ] } \ No newline at end of file diff --git a/Settings.json b/Settings.json index 8c7b4d5..a754aac 100644 --- a/Settings.json +++ b/Settings.json @@ -6,8 +6,8 @@ // Timeframe for the profit calculation, can be Live or Day "ProfitTimeframe": "Live", // Comma seperated string with the pool profit providers. Order is important, the first ones are preferred. - // Available: MineCryptonightApi, MinerRocksApi, CryptoknightCCApi (disabled by default because it's a bit slow) - "PoolProfitProviders": "MinerRocksApi,MineCryptonightApi", + // Available: MineCryptonightApi, CryptunitApi, MinerRocksApi, CryptoknightCCApi (disabled by default because it's a bit slow) + "PoolProfitProviders": "MinerRocksApi,CryptunitApi,MineCryptonightApi", // Set the strategy of profit switching, can be: // MaximizeFiat: Will maximize the profit in US dollar (default) // MaximizeCoins: Will try to maximize coin reward by comparing the current reward with the reward of the last 24 hours, this setting will ignore the price of the coins and is only compatible with miner.rocks profit provider @@ -17,6 +17,8 @@ "ProfitCheckInterval": 60, // Time in seconds until a profit switch can happen again "ProfitSwitchCooldown": 0, + // Threshold between current profit and most profitable coin before switching (e.g. 0 means switch immediately, 0.1 means switch when the most profitable coin is 10% percent more profitable than current) + "ProfitSwitchThreshold": 0, // Time in seconds between update of current status "DisplayUpdateInterval": 10, // Path to script that runs when reset is executed, can be null. @@ -27,6 +29,8 @@ "StartMinerMinimized": false, // Enable or disable caching of JSON Api calls, can be true or false "EnableCaching": true, + // Enable or disable logging, can be true or false + "EnableLogging": true, // Enable or disable watchdog (compares actual hashrate with expected hashrate and resets if certain conditions are met), can be true or false "EnableWatchdog": true, // Delay in seconds before watchdog starts diff --git a/XmrStak/amd_heavy.txt b/XmrStak/amd_heavy.txt index 23f0e9d..ca797ec 100644 --- a/XmrStak/amd_heavy.txt +++ b/XmrStak/amd_heavy.txt @@ -1,8 +1,8 @@  "gpu_threads_conf" : [ - { "index" : 0, "intensity" : 960, "worksize" : 8, "affine_to_cpu" : true, "strided_index" : 2, "mem_chunk" : 5, "comp_mode" : true }, - { "index" : 0, "intensity" : 960, "worksize" : 8, "affine_to_cpu" : true, "strided_index" : 2, "mem_chunk" : 5, "comp_mode" : true }, - { "index" : 1, "intensity" : 880, "worksize" : 8, "affine_to_cpu" : true, "strided_index" : 2, "mem_chunk" : 5, "comp_mode" : true }, - { "index" : 1, "intensity" : 880, "worksize" : 8, "affine_to_cpu" : true, "strided_index" : 2, "mem_chunk" : 5, "comp_mode" : true }, + { "index" : 0, "intensity" : 968, "worksize" : 8, "affine_to_cpu" : 1, "strided_index" : 2, "mem_chunk" : 8, "comp_mode" : false }, + { "index" : 0, "intensity" : 968, "worksize" : 8, "affine_to_cpu" : 1, "strided_index" : 2, "mem_chunk" : 8, "comp_mode" : false }, + { "index" : 1, "intensity" : 952, "worksize" : 8, "affine_to_cpu" : 1, "strided_index" : 2, "mem_chunk" : 8, "comp_mode" : false }, + { "index" : 1, "intensity" : 952, "worksize" : 8, "affine_to_cpu" : 1, "strided_index" : 2, "mem_chunk" : 8, "comp_mode" : false }, ], "platform_index" : 0, diff --git a/XmrStak/amd_v7.txt b/XmrStak/amd_v7.txt index 3e10325..5ac98a0 100644 --- a/XmrStak/amd_v7.txt +++ b/XmrStak/amd_v7.txt @@ -1,8 +1,8 @@  "gpu_threads_conf" : [ - { "index" : 0, "intensity" : 1932, "worksize" : 8, "affine_to_cpu" : true, "strided_index" : 2, "mem_chunk" : 5, "comp_mode" : true }, - { "index" : 0, "intensity" : 1932, "worksize" : 8, "affine_to_cpu" : true, "strided_index" : 2, "mem_chunk" : 5, "comp_mode" : true }, - { "index" : 1, "intensity" : 1760, "worksize" : 8, "affine_to_cpu" : true, "strided_index" : 2, "mem_chunk" : 5, "comp_mode" : true }, - { "index" : 1, "intensity" : 1760, "worksize" : 8, "affine_to_cpu" : true, "strided_index" : 2, "mem_chunk" : 5, "comp_mode" : true }, + { "index" : 0, "intensity" : 1920, "worksize" : 16, "affine_to_cpu" : 1, "strided_index" : 2, "mem_chunk" : 16, "comp_mode" : false }, + { "index" : 0, "intensity" : 1920, "worksize" : 16, "affine_to_cpu" : 1, "strided_index" : 2, "mem_chunk" : 16, "comp_mode" : false }, + { "index" : 1, "intensity" : 1888, "worksize" : 16, "affine_to_cpu" : 1, "strided_index" : 2, "mem_chunk" : 16, "comp_mode" : false }, + { "index" : 1, "intensity" : 1888, "worksize" : 16, "affine_to_cpu" : 1, "strided_index" : 2, "mem_chunk" : 16, "comp_mode" : false }, ], "platform_index" : 0, diff --git a/version.txt b/version.txt index fd406d8..e8c61fe 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -7 \ No newline at end of file +8 \ No newline at end of file