.cmd prerun files
+
+Miner Updates:
+- SRBMminerMulti-v0.5.3
+- XmRig-v6.3.5
+
+
+Changelog NemosMiner 3.9.9.5 Beta2 03.10.2020
+=============================================
+
+Miner Updates:
+- lolMiner-v1.0.9
+
+Fixed:
+- Fixed typo in configedit.html
+
+
+Changelog NemosMiner 02.10.2020
+===============================
+
+Miner Updates:
+- NBMiner-v32.0
+- TeamRed-v0.7.12
+
+
+Changelog NemosMiner 31.09.2020
+===============================
+
+Miner Updates:
+- Gminer-v2.26
+
+
+Changelog NemosMiner 30.09.2020
+===============================
+
+Added:
+- Web GUI: Rig Monitor
+- Web GUI: List of unprofitable algorithms
+
+Fixed:
+- API: Fix StatName when removing PowerUsage stat
+- Miner: Active (this run / total)
+
+Miner Updates:
+- Gminer-v2.25
+- TeamRed-v0.7.11
+- Wildrig-v0.27.6
+
+
+Changelog NemosMiner 28.09.2020
+===============================
+
+Enhancements:
+- Faster launching of miners
+- Only read power usage from HWiNFO/registry when miner does not expose power usage in miner API (uses less memory)
+- Filter miner/algorithms that are not supported on AMD RX5700
+
+Fixed:
+- Bminer-v16.3.1 Ethash protocol
+
+Miner Updates:
+- Bminer-v16.3.1
+- Gminer-v2.24
+- SRBMiner-Multi-v0.5.2
+- TeamRed-v0.7.10
+- Trex-v0.17.3
+- Wildrig-v0.27.3
+
+
+Changelog NemosMiner 09.09.2020
+===============================
+
+Miner Update:
+- SRBMiner-Multi-v0.5.1
+
+
+Changelog NemosMiner 07.09.2020
+===============================
+
+Breaking changes (from main code base):
+- Miner files are not backwards compatible
+- Pool files are not backwards compatible
+
+Fixed:
+- NiceHash balances not working
+- BalancesTracker reporting incorrect data
+
+Miner Updates:
+- Bminer-v16.3.0
+- GMiner 2.22
+- SRBMiner-Multi-v0.5.0
+- Trex-v0.16.2
+
+Changelog NemosMiner 02.09.2020
+===============================
+
+Breaking changes (from main code base):
+- Miner files are not backwards compatible
+- Pool files are not backwards compatible
+
+Fixed:
+- WDDM Device detection under Windows 7 & Windows 8.1
+
+Enhancements:
+- Faster loading of pool & miner data, even when running CPU miners
+
+Added:
+- UnprofitableAlgorithm list (".\Includes\UnprofitableAlgorithms.txt")
+ Syntax:
+ "*:[AlgorithmName]" = Algo is unprofitable as primary AND secondary algorithm
+ "1:[AlgorithmName]" = Algo is unprofitable as primary algorithm, but profitable as secondary algorithm
+ "2:[AlgorithmName]" = Algo is unprofitable as secondary algorithm, but profitable as primary algorithm
+- NBMiner: Support for 'DisableMinerFees' parameter (0% Fee)
+
+Known Issues:
+- NiceHash balances not working (t.b.d.)
+- BalancesTracker reporting incorrect data (t.b.d.)
+
+Changelog NemosMiner 29.08.2020
+===============================
+
+Breaking changes (from main code base):
+- Miner files are not backwards compatible
+- Pool files are not backwards compatible
+
+Fixed:
+- Miner device ID order
+
+Added:
+- Support for non-BTC currencies
+
+Known Issues:
+- NiceHash balances not working (t.b.d)
+- BalancesTracker not reporting NiceHash data (-> Sum of all balances too low)
+
+Changelog NemosMiner 22.08.2020
+===============================
+
+Breaking changes (from main code base):
+- Miner files are not backwards compatible
+- Pool files are not backwards compatible
+
+Fixed:
+- Automatic upgrade of config file (rename changed items, remove defunct parameters)
+- Documentation for power readout with HwINFO64 (ConfigHWinfo64.pdf)
+
+Enhancements:
+- Optimized pools / miners code
+- Config editor in Web GUI
+
+Miner Updates:
+- Bminer-v16.2.13
+- NanoMiner-v1.10.1
+- lolMiner-v1.0.7
+- Trex-v0.16.1
+
+Known Issues:
+- NiceHash balances not working (t.b.d)
+- BalancesTracker not reporting NiceHash data (-> Sum of all balances too low)
+
+Changelog NemosMiner 09.08.2020
+===============================
+
+New:
+- Added Support for ProHashing24hr (No balance processing yet)
+- Config items:
+ - MPHUserName
+ - NiceHashInternalWallet, NicehashAPIKey
+ - ProHashingAPIKey, ProHashingUserName
+
+Changed:
+- Config property APIKEY changed to MPHAPIKey
+- Renamed NiceHashV2 to NiceHash
+
+Fixed:
+- Watchdogs not clearing / refreshing in certain scenarios
+
+
+Changelog NemosMiner 07.08.2020
+===============================
+
+Breaking changes (from main code base):
+- Pool files are not backwards compatible
+- Miner files are not backwards compatible
+
+Changed:
+- EarningsTracker renamed to BalanceTracker (note: file structure remains compatible, so files data & config fuile can be renamed manually if required)
+- Remove defunct properties 'Type,
+
+Fixed:
+- Watchdogs not clearing / refreshing in certain scenarios
+- MPH Pool: Added MarginOfError property
+
+Enhancements:
+- Miners:
+ - Added TotalMiningDuration property (also available in Web GUI)
+- Web GUI:
+ - Minor tweaks & Typos
+
+Miner Update:
+- lolMiner-v1.06
+- TeamRedMiner-v0.7.9
+
+Changelog NemosMiner 04.08.2020
+===============================
+
+Breaking changes (from main code base):
+- Pool files are not backwards compatible
+- Miner files are not backwards compatible
+
+Added:
+- Watchdog functionality (Config items 'Watchdog*')
+
+Miner Update:
+- CryptoDredge-v0.24
+- lolMiner-v1.05
+- PhoenixMiner-v5.1c
+
+Changelog NemosMiner 27.07.2020
+===============================
+
+Breaking changes (from main code base):
+- Pool files are not backwards compatible
+- Miner files are not backwards compatible
+
+Added:
+- Mining start/pause/stop control to the Web GUI
+
+Fixed:
+- Mining when Idle (Idle detection)
+
+Changelog NemosMiner 21.07.2020
+===============================
+
+Breaking changes (from main code base):
+- Pool files are not backwards compatible
+- Miner files are not backwards compatible
+$Variables.NewMiners_Jobs
+Added:
+- Bad share detection (Config Item 'AllowedBadShareRatio')
+- More miners for AMD platform
+
+Changed:
+- Added column 'ApiRequestUri' to running miners (Web GUI)
+- use API modular API files for hash rate collection
+- Miners: Enabled separate miner instance per GPU model (helps to improve profit rates on mixed rigs)
+
+Changelog NemosMiner 28.06.2020
+===============================
+
+Breaking changes (from main code base):
+- Pool files are not backwards compatible
+- Miner files are not backwards compatible
+
+Changed:
+- Automatically convert config file (fixes breaking changes for config item change 'Location' & ActiveMinergain')
+ - ActiveMinerGainPct -> RunningMinerGainPct
+ - Location -> Region
+ - Remove defunct properties 'API_ID, API_Key, DisableGPU0, FirstInterval, IsFixedSize, IsReadOnly, IsSynchronized, Location, ManualConfig, SyncRoot'
+ - Add all new config items with their default values to existing config file
+
+What's still broken:
+- Idle detection (fixed since 27.07.2020)
+
+Changelog NemosMiner 28.06.2020
+===============================
+
+Breaking changes (from main code base):
+- Changed config item 'Location' to 'Region' -> requires manual change in config file
+- Pool files are not backwards compatible
+- New data format of SwitchingLog.txt -> need to delete old file manually
+- Changed config item 'ActiveMinerGainPct' to 'RunningMinerGainPct' -> Item will be renamed in config on start (Since 28.06.2020)
+
+Added:
+- Basic log viewer in Web GUI
+- Earnings statistics in Web GUI
+
+Changed:
+- Removed redundant charting code
+- Moved Get-NextColor to includes.psm1
+
+Fixed:
+- Earnings display in GUI
+- Date sort order in charting
+
+What's still broken:
+- Idle detection (fixed since 27.07.2020)
+
+Todo:
+- Move config dialog to Web GUI
+- Move charts to Web GUI
+- Move Monitoring to Web GUI
+- Enhance miners to support device filters (e.g. available vram, disabled devices etc.)
+
+
+Changelog NemosMiner 23.06.2020
+===============================
+
+Changed:
+- New data format of SwitchingLog.txt -> need to delete old file manually
+- Icons in web GUI
+- Removed some device config from GUI (WIP!)
+
+Added:
+- SwitchingLog info now available in web GUI
+
+Fixed:
+- Power readout was 33% too small (-> Power usage data needs to be re-measured for all miners)
+
+Breaking changes (from main code base):
+- Changed config item 'Location' to 'Region' -> requires manual change in config file
+- Changed pool property 'EarningsAdjustmentFactor' to 'EstimateCorrection' (should be added to PoolsConfig to make it a per pool config item)
+- Pool files are not backwards compatible
+- New data format of SwitchingLog.txt -> need to delete old file manually
+- Changed config item 'ActiveMinerGainPct' to 'RunningMinerGainPct' -> Item will be renamed in config on start (Since 28.06.2020)
+
+
+Changelog NemosMiner 21.06.2020
+===============================
+
+Fixed:
+- ZergPool / ZPool: Password currency was empty
+- Earnings display in GUI
+
+Changed:
+- GUI: Moved 'Earnings' information to separate tab
+
+What's still broken:
+- Idle detection (fixed since 27.07.2020)
+
+
+Changelog NemosMiner 17.06.2020
+===============================
+
+Fixed:
+- Fix endless loop when a miner has died
+
+Changed:
+- Remove de-configured pools from pool collection
+
+Added:
+- Near-Compatibility to MultiPoolMiner based miners, supports per-device miner instances (requires a simple path change in each MPM miner file)
+
+What's still broken:
+- Idle detection (fixed since 27.07.2020)
+- Earnings display in GUI (fixed)
+
+
+Changelog NemosMiner 16.06.2020
+===============================
+
+Fixed:
+- Downloader only downloading required miners
+- Stop miner gracefully when miner file gets removed while NemosMiner is running
+- Mining to correct address at start or end of donation
+- Do not switch miners while donating
+
+What's still broken:
+- Idle detection (fixed since 27.07.2020)
+- Earnings display in GUI (fixed)
+
+Changelog NemosMiner 14.06.2020
+===============================
+
+Fixed:
+- Downloader
+- Miner fee calculation (now done in core)
+
+Changed:
+- For all miner files:
+ - Removed 'Hashrate' property
+ - Added 'Hashrate' property instead. Hashrate calculation is done in core
+ - Added 'Fee' property (OptionalMiners)
+
+Added:
+- New config items 'NoDualAlgoMining' & 'NoSingleAlgoMining'
+
+Changelog NemosMiner 11.06.2020
+===============================
+
+Main improvements:
+- No doubling of miners after donation
+- Less switching while donating
+
+What's still broken:
+- Idle detection (fixed since 27.07.2020)
+
+Fixed:
+- algo selection does not seem to be working
+- running time starts at 12hour not 0
+- donation mining is not passing the c=BTC
+- Typos
+- Error '-AsHashtable'
+- Start / Pause / Stop from GUI
+
+Changed:
+- Donation is randomized to a different time every day.
+
+Changelog NemosMiner 08.06.2020
+===============================
+
+Main improvements:
+- Better hash rate state stability
+- Power usage measurement and true profit calculation
+- Shorter benchmark times
+- Changed code to use to use classes & methods
+
+What's broken:
+- Start / Pause / Stop from GUI
+- Idle detection
+
+Breaking changes:
+- Changed config item 'Location' to 'Region' -> requires manual change in config file
+- Changed pool property 'EarningsAdjustmentFactor' to 'EstimateCorrection' (should be added to PoolsConfig to make it a per pool config item)
+- Pool files are not backwards compatible
+
+Added:
+- Basic Web GUI
+- New config parameters (see New Config Items.txt)
+- All config parameters are available as command line parameters
+- Automatically add missing config parameters to config file
+- Print message when hash rate was collected
+- Detect miners with unreal earning (> 5x higher than the next best 10% miners, error in data provided by pool?
+- Support for external log viewer (Download Snaketail from https://github.com/snakefoot/snaketail-net/releases and put in '\Utils' folder)
+
+Changed:
+- Changed Core.ps1 & Includes.ps1 to modules
+- Use jobs for reading data from miners (hashrate & power usage), this gives more samples & and more reliable numbers
+- Changed 'IsLoaded' to 'using module'
+
+Fixed:
+- Property Fee in Pools.
+- Earnings tracker working again
+- Various cosmetic fixes
+
+Removed:
+- Separate PowerUsage job
+- Config parameter "FirstInterval"
+- Removed config Item 'FirstInterval'. (If in config file it will be ignored)
+- Removed config item 'StatsInterval'. (If in config file it will be ignored)
+
+Todo:
+- Extend config dialog for new config options
+- Make a proper web interface to replace GUI
+- Change devices selection from 'Type' to device names.
\ No newline at end of file
diff --git a/Changed Config Items.txt b/Changed Config Items.txt
new file mode 100644
index 0000000000..2cdeca50ed
--- /dev/null
+++ b/Changed Config Items.txt
@@ -0,0 +1,290 @@
+Note: NemosMiner will automatically update existing config files during updates. Changed config items will get renamed / removed or converted as needed.
+It is recommended to review the updated configuration after an update.
+
+
+New Config Items
+================
+
+# If set API will log all requests to this file, to disable leave empty
+ "APILogfile": "",
+
+# Acceptable bad share threshold ((bad + rejected + stale) / total) as reported by the miner. If the ratio is exceeded the miner will marked as failed. Allowed values: 0.00 - 1.00. Default of 0 disables this check
+ "BadShareRatioThreshold": 0.05,
+
+# Balances tracker will not track these pools (use pool base name without 24hr/Coins/Plus etc.)
+ "BalancesTrackerIgnorePool": [
+ "AHashPool",
+ ],
+
+# If true NemosMiner will store all balance tracker data in .\Logs\EarningTrackerLog.csv
+ "BalancesTrackerLog": false,
+
+# Interval duration (in munutes) to trigger background task to collect pool balances & earnings dataset to 0 to disable
+ "BalancesTrackerPollInterval": 5,
+
+# If true, power usage will be read from miners and calculate power cost, required for true profit calculation
+ "CalculatePowerCost": true,
+
+# Process priority for CPU miners
+ "CPUMinerProcessPriority": -2,
+
+# If true NemosMiner will not use any single algo miners
+ "DisableSingleAlgoMining": false,
+
+# Set to true to disable miner fees (Note: not all miners support turning off their built in fees, others will reduce the hashrate)
+ "DisableMinerFee": false,
+
+# If true all miners which contain fees are disabled
+ "DisableMinersWithFee": false,
+
+# If true NemosMiner will not use any dual algo miners
+ "DisableDualAlgoMining": false,
+
+# Excluded device names, all devices not explicitly excluded will be active
+ "ExcludeDeviceName": [
+ "CPU#00",
+ "GPU#02"
+ ],
+
+# Extra currencies, i.e. GBP, USD, AUD, NZD ect., but also other crypto currencies, e.g. ETC, LTC, used in balances summary
+ "ExtraCurrencies": [
+ "USD",
+ "ETC"
+ ],
+
+# Process priority for GPU miners
+ "GPUMinerProcessPriority": -1,
+
+# Powerusage of idle system in Watt. Part of profit calculation
+ "IdlePowerUsageW": 60,
+
+# Time in seconds the system must be idle before mining starts (only if MineWhenIdle -eq $true)
+ "IdleSec": 120,
+
+# If true, NM will ignore miner fee for earning & profit calculation
+ "IgnoreMinerFee": false,
+
+# If true NM will ignore pool fee for earning & profit calculation
+ "IgnorePoolFee": false,
+
+# If true, NM will ignore power cost in best miner selection, instead miners with best earnings will be selected
+ "IgnorePowerCost": false,
+
+# If true, use the miners in the 'LegacyMiners' directory (Miners based on the original MultiPoolMiner format)
+ "IncludeLegacyMiners": true,
+
+# If true NemosMiner will log the pool balance API data
+ "LogBalanceAPIResponse": false,
+
+# Log level detail to be written to log file, see Write-Message function
+ "LogFile": [
+ "Info",
+ "Warn",
+ "Error",
+ "Verbose",
+ "Debug"
+ ],
+
+# Log level detail to be written to screen, see Write-Message function
+ "LogScreen": [
+ "Info",
+ "Warn",
+ "Error",
+ "Verbose",
+ "Debug"
+ ],
+
+# Use only pools with price accuracy greater than the configured value. Allowed values: 0.0 - 1.0 (0% - 100%)
+ "MinAccuracy": 0.5,
+
+# Minimum number of hash rate samples required to store hash rate
+ "MinDataSamples": 20,
+
+# Per algo multiply MinHashRateSamples by this value
+ "MinDataSamplesAlgoMultiplier": {
+ "X25r" = 3
+ }
+
+# Minimum intervals a miner must mine continously the same available algo@pool before switching is allowed (e.g. 3 would force a miner to stick mining algo@pool for min. 3 intervals before switching to another algo or pool)
+ "MinInterval": 1,
+
+# If true NemosMiner will create separate miner instances per device model. This will increase profitability. (WIP: Need to change each miner to support this new feature)
+ "MinerInstancePerDeviceModel": true,
+
+# 0: Use best miner per algorithm and device only; 1: Use optimal miners (more than one per algorithm and device); 2: Use all miners per algorithm and device;
+ "MinerSet": 1,
+
+# Show miner windows either "minimized": miner window is minimized, but accessible; "normal": miner windows are shown normally; "hidden": miners will run as a hidden background task and are not accessible (not recommended)
+ "MinerWindowStyle": = "minimized",
+
+# If true Miner window is shown normal when benchmarking (recommended to better see miner messages)
+ "MinerWindowStyleNormalWhenBenchmarking": true,
+
+# MiningPoolHub API Key (required to retrieve balance information)
+ "MinungPoolHubAPIKey": "",
+
+# MiningPoolHub UserName, if left empty then $UserName is used
+ "MiningPoolHubUserName": "",
+
+# NiceHash API Key (required to retrieve balance information)
+ "NicehashAPIKey": "",
+
+# Set to $true if NiceHashWallet is a NiceHash internal Wallet (lower pool fees)
+ "NiceHashWalletIsInternal": false,
+
+# NiceHash wallet, if left empty $Wallet is used
+ "NiceHashWallet": "",
+
+# NiceHash Organization Id (required to retrieve balance information)
+ "NicehashOrganizationId": "",
+
+# If true, NemosMiner will open firewall ports for all miners (requires admin rights!)
+ "OpenFirewallPorts": true,
+
+# Default factor with which NemosMiner multiplies the prices reported by ALL pools. The default value is 1 (valid range is from 0.1 to 1.0).
+# E.g. If you feel that the general profit estimations as reported by MPM are too high, e.g. %20, then set '-EarningsAdjustmentFactor' to 0.8.
+ "EarningsAdjustmentFactor": 1,
+
+# NemosMiner will poll rig monitoring server every n minutes. Allowed values 0 - 60 minutes. 0 will disable polling
+ "RigMonitorPollInterval": 5,
+
+# Time (in seconds) until NemosMiner aborts the pool request (useful if a pool's API is stuck). Note: do not make this value too small or you will not get an pool data
+ "PoolTimeout": 30,
+
+# Price of power per kW⋅h (in $Currency, e.g. CHF), valid from HH:mm (24hr format)
+ "PowerPricekWh": {
+ "00:00": 0.26,
+ "12:00": 0.3
+ },
+
+# Minimum profit threshold, if profit is less than the configured value (in $Currency, e.g. CHF) mining will stop (except for benchmarking & power usage measuring)
+ "ProfitabilityThreshold": 0,
+
+# Static power usage per device in W, e.g. @{ "GPU#03" = 25, "GPU#04 = 55" } (in case HWiNFO cannot read power usage)
+ "PowerUsage": {
+ },
+
+# ProHashing API Key (required to retrieve balance information)
+ "ProHashingAPIKey": "",
+
+# ProHashing Mining Mode, Either PPS (Pay Per Share) or PPLNS (Pay per Last N Shares)
+ "ProHashingMiningMode": "PPS",
+
+# ProHashing UserName, if left empty then $UserName is used
+ "ProHashingUserName": "",
+
+# One of europe/us/asia
+ "Region": "Europe",
+
+# Show pool data accuracy column in miner overview
+ "ShowAccuracy": true,
+
+# Always show all miners in miner overview (if $false, only the best miners will be shown except when in benchmark / powerusage measurement)
+ "ShowAllMiner": false,
+
+# Show CoinName column in miner overview
+ "ShowCoinName": true,
+
+# Show Currency column in miner overview
+ "ShowCurrency": true,
+
+# Show miner earning column in miner overview
+ "ShowEarning": true,
+
+# Show miner earning bias column in miner overview
+ "ShowEarningBias": true,
+
+# Show miner fee column in miner overview (if fees are available, Property '[Double]Fee')
+ "ShowMinerFee": true,
+
+# Show pool fee column in miner overview (if fees are available, Property '[Double]Fee')
+ "ShowPoolFee": true,
+
+# Show Power cost column in miner overview (if power price is available, see PowerPricekWh)
+ "ShowPowerCost": true,
+
+# Show miner profit column in miner overview (if power price is available, see PowerPricekWh)
+ "ShowProfit": true,
+
+# Show miner profit bias column in miner overview (if power price is available, see PowerPricekWh)
+ "ShowProfitBias": true,
+
+# Show Power usage column in miner overview (if power price is available, see PowerPricekWh)
+ "ShowPowerUsage": true,
+
+# Path to optional external log reader (SnakeTail) [https://github.com/snakefoot/snaketail-net]
+ "SnakeTailExe": ".\Utils\SnakeTail.exe",
+
+# One of 'Idle', 'Paused' or 'Running'. This is the same as the buttons in the Web GUI
+ "StartupMode": false,
+
+# If true, NM will ignore rejected shares when measuring hashrates
+ "SubtractBadShares": true,
+
+# Current pool prices must all be all with 'SyncWindow' minutes, otherwise stable price will be used insted of the biased value and a warning will be shown
+ "SyncWindow": 5,
+
+# If true write transcript files to log folder
+ "Transcript": false,
+
+# Ignore pool if price is more than $UnrealPoolPriceFactor higher than average price of all other pools with same algo & currency
+ "UnrealPoolPriceFactor": 3,
+
+# Ignore pool if price is more than $UnrealMinerEarningFactor higher than average price of all other miners with same algo & currency
+ "UnrealMinerEarningFactor": 3,
+
+# If true pools (currently ZergPool only) will use anycast for best network performance and ping times
+ "UseAnycast": $false,
+
+# If true NemosMiner will apply miner specific tweaks, e.g mild overclock. This may improve profitability at the expense of system stability (Admin rights are required)
+ "UseMinerTweaks:" false,
+
+# If true NemosMiner will display BTC values in mBTC (BTC/1000)
+ "UsemBTC": true,
+
+# First value: time (in seconds) until first hash rate sample is valid (default 0, accept first sample), second value: time (in seconds) the miner is allowed to warm up, e.g. to compile the binaries or to get the API ready and providing first data samples before it get marked as failed. Default 15 (seconds).
+ "WarmupTimes" = [0, 15],
+
+# Wallets.[Currency=WalletAdrress]; one entry per currency
+ $Wallets: {
+ "BTC" = "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
+ "ETC" = "0x7CF99ec9029A98AFd385f106A93977D8105Fec0f",
+ "ETH" = "0x92e6F22C1493289e6AD2768E1F502Fc5b414a287"
+ },
+
+# Number of watchdog timers with same algorithm name & algorithm until miner/algo combination gets suspended
+ "WatchdogMinerAlgorithmCount": 3,
+
+# Number of watchdog timers with same miner name until miner gets suspended
+ "WatchdogMinerCount": 6,
+
+# Number of watchdog timers with same pool name & algorithm until pool/algo combination gets suspended
+ "WatchdogPoolAlgorithmCount": 3,
+
+# Number of watchdog timers with same pool name until pool gets suspended
+ "WatchdogPoolCount": 7,
+
+# If true launch Web GUI (default: true, to disable add ' -Webgui:false' to your NemosMiner start file)
+ "WebGUI" = $true,
+
+Removed Config Items
+====================
+ "APIKey": "", (Replaced with ProHashingAPIKey & ProHashingAPIKey)
+ "EstimateCorrection": false, obsolete. Accuracy & Bias reduce prices which in turn avoids pools with high price fluctuation
+ "GPUCount": 1, obsolete
+ "HideConsole": false, obsolete
+ "MarginOfError": 0,4, obsolete
+ "RunningMinerGainPct": Renamed to "MinerSwitchingThreshold"
+ "SelGPUDSTM": "0 1", obsolete; replaced with per device configuration option "ExcludeDeviceName"
+ "SelGPUCC": "0,1", obsolete; replaced with per device configuration option "ExcludeDeviceName"
+ "SSL": not supported until a later release
+ "Type": ["AMD", "CPU", "NVIDIA"], obsolete; replaced with per device configuration option "ExcludeDeviceName"
+ "TypeAMD": true, obsolete; replaced with per device configuration option "ExcludeDeviceName"
+ "TypeCPU": true, obsolete; replaced with per device configuration option "ExcludeDeviceName"
+ "TypeNVIDIA": true, obsolete; replaced with per device configuration option "ExcludeDeviceName"
+ "UserName": "", (Replaced with NiceHashUserName & ProHashingUsername)
+ "Wallet": [BTC Address]; replaced with "Wallets.BTC"
+
+NiceHash pool Config:
+=====================
+- Added 'IsInternal' flag (lower fee of 2% instad of 5%), see .\Config.PoolsConfig-NiceHashInternal.json for an example
diff --git a/Config/PoolsConfig-ExampleAll.json b/Config/PoolsConfig-ExampleAll.json
deleted file mode 100644
index d0d50c0c0d..0000000000
--- a/Config/PoolsConfig-ExampleAll.json
+++ /dev/null
@@ -1,111 +0,0 @@
-{
- "default": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- },
- "ahashpool": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner3.0",
- "PricePenaltyFactor": 1
- },
- "ahashpool24hr": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- },
- "ahashpoolplus": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- },
- "blazepool": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- },
- "blazepool24hr": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- },
- "blazepoolplus": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- },
- "hashrefinery": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- },
- "minemoney": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- },
- "minemoney24hr": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- },
- "miningpoolhub": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "NemosMiner",
- "PricePenaltyFactor": 1,
- "APIKey": ""
- },
- "nicehash": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "NemosMiner",
- "PricePenaltyFactor": 1
- },
- "zergpool": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- },
- "zergpool24hr": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- },
- "zergpoolplus": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- },
- "zpool": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- },
- "zpool24hr": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- },
- "zpoolplus": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- }
-}
diff --git a/Config/PoolsConfig-NHInternal.json b/Config/PoolsConfig-NHInternal.json
deleted file mode 100644
index ee4bc40201..0000000000
--- a/Config/PoolsConfig-NHInternal.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "default": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "ID=NemosMiner",
- "PricePenaltyFactor": 1
- },
- "nicehash": {
- "UserName": "nemo",
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "NemosMiner",
- "PricePenaltyFactor": 1
- }
-}
diff --git a/Config/PoolsConfig-x21sOnPhiPhi.json b/Config/PoolsConfig-x21sOnPhiPhi.json
deleted file mode 100644
index eba887fe27..0000000000
--- a/Config/PoolsConfig-x21sOnPhiPhi.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "default": {
- "PricePenaltyFactor": 1,
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "UserName": "nemo",
- "WorkerName": "NemosMiner",
- "APIKey": ""
- },
- "phiphipoolplus": {
- "PricePenaltyFactor": 0.97,
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "UserName": "nemo",
- "WorkerName": "NemosMiner",
- "APIKey": "",
- "Algorithm": [
- "+x21s"
- ]
- }
-}
diff --git a/Config/PoolsConfig.json b/Config/PoolsConfig.json
deleted file mode 100644
index d85294fe2b..0000000000
--- a/Config/PoolsConfig.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "default": {
- "PricePenaltyFactor": 1,
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "UserName": "nemo",
- "WorkerName": "ID=NemosMiner",
- "APIKey": ""
- }
-}
diff --git a/Config/Version.json b/Config/Version.json
deleted file mode 100644
index 529c0c3df8..0000000000
--- a/Config/Version.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "Product": "NemosMiner",
- "Version": "3.8.0.0",
- "Update": false,
- "Message": "https://github.com/nemosminer/NemosMiner/releases"
-}
diff --git a/Config/config.json b/Config/config.json
deleted file mode 100644
index 407a7a054c..0000000000
--- a/Config/config.json
+++ /dev/null
@@ -1,66 +0,0 @@
-{
- "ActiveMinerGainPct": 24,
- "Algorithm": [
- ""
- ],
- "API_ID": 0,
- "API_Key": "",
- "APIKEY": "373a71335e010d6928766a5cce6365b5e7f75ef798d0f6353ceca27f782d795b",
- "Autostart": false,
- "AutoUpdate": false,
- "Count": 0,
- "Currency": "USD",
- "Delay": 1,
- "DisableGPU0": false,
- "Donate": 5,
- "EnableEarningsTrackerLogs": false,
- "FirstInterval": 30,
- "HideConsole": false,
- "IdleSec": 120,
- "IncludeOptionalMiners": false,
- "IncludeRegularMiners": false,
- "Interval": 120,
- "IsFixedSize": false,
- "IsReadOnly": false,
- "IsSynchronized": true,
- "Keys": [
-
- ],
- "Location": "US",
- "ManualConfig": false,
- "MarginOfError": 0,
- "MinerName": null,
- "MineWhenIdle": false,
- "MonitoringServer": "https://nemosminer.com",
- "MonitoringUser": "",
- "Passwordcurrency": "BTC",
- "PoolName": [
- "zpoolplus",
- "miningpoolhub",
- "nlpoolplus",
- "nicehash",
- "zergpoolplus"
- ],
- "Proxy": "",
- "ReportToServer": false,
- "SSL": false,
- "StartGUIMinimized": false,
- "StartPaused": false,
- "StatsInterval": 180,
- "SyncRoot": {
-
- },
- "TrackEarnings": true,
- "Type": [
- "NVIDIA"
- ],
- "TypeCPU": false,
- "TypeNVIDIA": true,
- "UIStyle": "Full",
- "UserName": "nemo",
- "Values": [
-
- ],
- "Wallet": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- "WorkerName": "NemosMiner"
-}
diff --git a/Config/poolapiref.json b/Config/poolapiref.json
deleted file mode 100644
index 583f43e8d6..0000000000
--- a/Config/poolapiref.json
+++ /dev/null
@@ -1,255 +0,0 @@
-[
- {
- "Name":"ahashpoolplus",
- "EarnTrackSupport":"yes",
- "PoolUri":"https://www.ahashpool.com",
- "WalletUri":"https://www.ahashpool.com/api/walletEx?address=",
- "StatusUri":"https://www.ahashpool.com/api/status",
- "CurrenciesUri":"https://www.ahashpool.com/api/currencies",
- "PaymentThreshold":0.003,
- "Total":"total_earned",
- "Balance":"balance"
- },
- {
- "Name":"ahashpool",
- "EarnTrackSupport":"yes",
- "PoolUri":"https://www.ahashpool.com",
- "WalletUri":"https://www.ahashpool.com/api/walletEx?address=",
- "StatusUri":"https://www.ahashpool.com/api/status",
- "CurrenciesUri":"https://www.ahashpool.com/api/currencies",
- "PaymentThreshold":0.003,
- "Total":"total_earned",
- "Balance":"balance"
- },
- {
- "Name":"ahashpool24hr",
- "EarnTrackSupport":"yes",
- "PoolUri":"https://www.ahashpool.com",
- "WalletUri":"https://www.ahashpool.com/api/walletEx?address=",
- "StatusUri":"https://www.ahashpool.com/api/status",
- "CurrenciesUri":"https://www.ahashpool.com/api/currencies",
- "PaymentThreshold":0.003,
- "Total":"total_earned",
- "Balance":"balance"
- },
- {
- "Name":"starpool",
- "EarnTrackSupport":"yes",
- "PoolUri":"https://www.starpool.biz",
- "WalletUri":"https://www.starpool.biz/api/walletEx?address=",
- "StatusUri":"https://www.starpool.biz/api/status",
- "CurrenciesUri":"https://www.starpool.biz/api/currencies",
- "PaymentThreshold":0.005,
- "Total":"total_earned",
- "Balance":"balance"
- },
- {
- "Name":"starpool24hr",
- "EarnTrackSupport":"yes",
- "PoolUri":"https://www.starpool.biz",
- "WalletUri":"https://www.starpool.biz/api/walletEx?address=",
- "StatusUri":"https://www.starpool.biz/api/status",
- "CurrenciesUri":"https://www.starpool.biz/api/currencies",
- "PaymentThreshold":0.005,
- "Total":"total_earned",
- "Balance":"balance"
- },
- {
- "Name":"starpoolPlus",
- "EarnTrackSupport":"yes",
- "PoolUri":"https://www.starpool.biz",
- "WalletUri":"https://www.starpool.biz/api/walletEx?address=",
- "StatusUri":"https://www.starpool.biz/api/status",
- "CurrenciesUri":"https://www.starpool.biz/api/currencies",
- "PaymentThreshold":0.005,
- "Total":"total_earned",
- "Balance":"balance"
- },
- {
- "Name":"blazepool",
- "EarnTrackSupport":"Yes",
- "PoolUri":"http://www.blazepool.com",
- "WalletUri":"http://api.blazepool.com/wallet/",
- "StatusUri":"http://api.blazepool.com/status",
- "CurrenciesUri":"",
- "PaymentThreshold":0.003,
- "Total":"total_earned",
- "Balance":"balance"
- },
- {
- "Name":"blazepool24hr",
- "EarnTrackSupport":"Yes",
- "PoolUri":"http://www.blazepool.com",
- "WalletUri":"http://api.blazepool.com/wallet/",
- "StatusUri":"http://api.blazepool.com/status",
- "CurrenciesUri":"",
- "PaymentThreshold":0.003,
- "Total":"total_earned",
- "Balance":"balance"
- },
- {
- "Name":"blazepoolplus",
- "EarnTrackSupport":"Yes",
- "PoolUri":"http://www.blazepool.com",
- "WalletUri":"http://api.blazepool.com/wallet/",
- "StatusUri":"http://api.blazepool.com/status",
- "CurrenciesUri":"",
- "PaymentThreshold":0.003,
- "Total":"total_earned",
- "Balance":"balance"
- },
- {
- "Name":"phiphipool",
- "EarnTrackSupport":"Yes",
- "PoolUri":"http://www.phiphipool.com",
- "WalletUri":"http://www.phi-phi-pool.com/api/wallet?address=",
- "StatusUri":"http://www.phi-phi-pool.com/api/status",
- "CurrenciesUri":"http://www.phi-phi-pool.com/api/currencies",
- "PaymentThreshold":0.005,
- "Total":"total_earned",
- "Balance":"balance"
- },
- {
- "Name":"phiphipool24hr",
- "EarnTrackSupport":"Yes",
- "PoolUri":"http://www.phiphipool.com",
- "WalletUri":"http://www.phi-phi-pool.com/api/wallet?address=",
- "StatusUri":"http://www.phi-phi-pool.com/api/status",
- "CurrenciesUri":"http://www.phi-phi-pool.com/api/currencies",
- "PaymentThreshold":0.005,
- "Total":"total_earned",
- "Balance":"balance"
- },
- {
- "Name":"phiphipoolplus",
- "EarnTrackSupport":"Yes",
- "PoolUri":"http://www.phiphipool.com",
- "WalletUri":"http://www.phi-phi-pool.com/api/wallet?address=",
- "StatusUri":"http://www.phi-phi-pool.com/api/status",
- "CurrenciesUri":"http://www.phi-phi-pool.com/api/currencies",
- "PaymentThreshold":0.005,
- "Total":"total_earned",
- "Balance":"balance"
- },
- {
- "Name":"blockmasters",
- "EarnTrackSupport":"Yes",
- "PoolUri":"http://blockmasters.co/",
- "WalletUri":"http://blockmasters.co/api/walletEx?address=",
- "StatusUri":"http://blockmasters.co/api/status",
- "CurrenciesUri":"http://blockmasters.co/api/currencies",
- "PaymentThreshold":0.005,
- "Total":"total",
- "Balance":"balance"
- },
- {
- "Name":"blockmasters24hr",
- "EarnTrackSupport":"Yes",
- "PoolUri":"http://blockmasters.co/",
- "WalletUri":"http://blockmasters.co/api/walletEx?address=",
- "StatusUri":"http://blockmasters.co/api/status",
- "CurrenciesUri":"http://blockmasters.co/api/currencies",
- "PaymentThreshold":0.005,
- "Total":"total",
- "Balance":"balance"
- },
- {
- "Name":"blockmastersplus",
- "EarnTrackSupport":"Yes",
- "PoolUri":"http://blockmasters.co/",
- "WalletUri":"http://blockmasters.co/api/walletEx?address=",
- "StatusUri":"http://blockmasters.co/api/status",
- "CurrenciesUri":"http://blockmasters.co/api/currencies",
- "PaymentThreshold":0.005,
- "Total":"total",
- "Balance":"balance"
- },
- {
- "Name":"hashrefinery",
- "EarnTrackSupport":"yes",
- "PoolUri":"https://pool.hashrefinery.com",
- "WalletUri":"https://pool.hashrefinery.com/api/walletEx?address=",
- "StatusUri":"https://pool.hashrefinery.com/api/status",
- "CurrenciesUri":"https://pool.hashrefinery.com/api/currencies",
- "PaymentThreshold":0.003,
- "Total":"total",
- "Balance":"balance"
- },
- {
- "Name":"hashrefineryplus",
- "EarnTrackSupport":"yes",
- "PoolUri":"https://pool.hashrefinery.com",
- "WalletUri":"https://pool.hashrefinery.com/api/walletEx?address=",
- "StatusUri":"https://pool.hashrefinery.com/api/status",
- "CurrenciesUri":"https://pool.hashrefinery.com/api/currencies",
- "PaymentThreshold":0.003,
- "Total":"total",
- "Balance":"balance"
- },
- {
- "Name":"hashrefinery24hr",
- "EarnTrackSupport":"yes",
- "PoolUri":"https://pool.hashrefinery.com",
- "WalletUri":"https://pool.hashrefinery.com/api/walletEx?address=",
- "StatusUri":"https://pool.hashrefinery.com/api/status",
- "CurrenciesUri":"https://pool.hashrefinery.com/api/currencies",
- "PaymentThreshold":0.003,
- "Total":"total",
- "Balance":"balance"
- },
- {
- "Name":"zpool",
- "EarnTrackSupport":"Yes",
- "PoolUri":"http://www.zpool.ca",
- "WalletUri":"http://www.zpool.ca/api/walletEx?address=",
- "StatusUri":"http://www.zpool.ca/api/status",
- "CurrenciesUri":"http://www.zpool.ca/api/currencies",
- "PaymentThreshold":0.0025,
- "Total":"total",
- "Balance":"balance"
- },
- {
- "Name":"zpool24hr",
- "EarnTrackSupport":"yes",
- "PoolUri":"http://www.zpool.ca",
- "WalletUri":"http://www.zpool.ca/api/walletEx?address=",
- "StatusUri":"http://www.zpool.ca/api/status",
- "CurrenciesUri":"http://www.zpool.ca/api/currencies",
- "PaymentThreshold":0.0025,
- "Total":"total",
- "Balance":"balance"
- },
- {
- "Name":"zpoolplus",
- "EarnTrackSupport":"yes",
- "PoolUri":"http://www.zpool.ca",
- "WalletUri":"http://www.zpool.ca/api/walletEx?address=",
- "StatusUri":"http://www.zpool.ca/api/status",
- "CurrenciesUri":"http://www.zpool.ca/api/currencies",
- "PaymentThreshold":0.0025,
- "Total":"total",
- "Balance":"balance"
- },
- {
- "Name":"miningpoolhub",
- "EarnTrackSupport":"yes",
- "PoolUri":"https://miningpoolhub.com/",
- "WalletUri":"https://miningpoolhub.com/index.php?page=api\u0026action=getuserallbalances\u0026api_key=",
- "StatusUri":"",
- "CurrenciesUri":"",
- "PaymentThreshold":0.01,
- "Total":"confirmed",
- "Balance":"confirmed"
- },
- {
- "Name":"nicehash",
- "EarnTrackSupport":"yes",
- "PoolUri":"http://www.nicehash.com",
- "WalletUri":"https://api.nicehash.com/api?method=stats.provider\u0026addr=",
- "StatusUri":"",
- "CurrenciesUri":"",
- "PaymentThreshold":0.001,
- "Total":"balance",
- "Balance":"balance"
- }
-]
diff --git a/ConfigHWinfo64.odt b/ConfigHWinfo64.odt
new file mode 100644
index 0000000000..804504185e
Binary files /dev/null and b/ConfigHWinfo64.odt differ
diff --git a/ConfigHWinfo64.pdf b/ConfigHWinfo64.pdf
new file mode 100644
index 0000000000..8b6969758b
Binary files /dev/null and b/ConfigHWinfo64.pdf differ
diff --git a/Core.ps1 b/Core.ps1
deleted file mode 100644
index 71391b2e23..0000000000
--- a/Core.ps1
+++ /dev/null
@@ -1,633 +0,0 @@
-<#
-Copyright (c) 2018-2019 Nemo and MrPlus
-NemosMiner is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-NemosMiner is distributed in the hope that it will be useful, See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-#>
-
-<#
-Product: NemosMiner
-File: Core.ps1
-version: 3.8.0.0
-version date: 16 May 2019
-#>
-
-Function InitApplication {
- $Variables | Add-Member -Force @{SourcesHash = @()}
- $Variables | Add-Member -Force @{ProcessorCount = (Get-WmiObject -class win32_processor).NumberOfLogicalProcessors}
-
- if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
- Set-Location (Split-Path $script:MyInvocation.MyCommand.Path)
-
- $Variables | Add-Member -Force @{ScriptStartDate = (Get-Date)}
- # GitHub Supporting only TLSv1.2 on feb 22 2018
- if ([Net.ServicePointManager]::SecurityProtocol -notmatch [Net.SecurityProtocolType]::Tls12) {
- [Net.ServicePointManager]::SecurityProtocol += [Net.SecurityProtocolType]::Tls12
- }
- # Force Culture to en-US
- $culture = [System.Globalization.CultureInfo]::CreateSpecificCulture("en-US")
- $culture.NumberFormat.NumberDecimalSeparator = "."
- $culture.NumberFormat.NumberGroupSeparator = ","
- [System.Threading.Thread]::CurrentThread.CurrentCulture = $culture
- Set-Location (Split-Path $script:MyInvocation.MyCommand.Path)
- #Set process priority to BelowNormal to avoid hash rate drops on systems with weak CPUs
- (Get-Process -Id $PID).PriorityClass = "BelowNormal"
-
- Import-Module NetSecurity -ErrorAction SilentlyContinue
- Import-Module Defender -ErrorAction SilentlyContinue
- Import-Module "$env:Windir\System32\WindowsPowerShell\v1.0\Modules\NetSecurity\NetSecurity.psd1" -ErrorAction SilentlyContinue
- Import-Module "$env:Windir\System32\WindowsPowerShell\v1.0\Modules\Defender\Defender.psd1" -ErrorAction SilentlyContinue
-
- if (Get-Command "Unblock-File" -ErrorAction SilentlyContinue) {Get-ChildItem . -Recurse | Unblock-File}
- if ((Get-Command "Get-MpPreference" -ErrorAction SilentlyContinue) -and (Get-MpComputerStatus -ErrorAction SilentlyContinue) -and (Get-MpPreference).ExclusionPath -notcontains (Convert-Path .)) {
- Start-Process (@{desktop = "powershell"; core = "pwsh"}.$PSEdition) "-Command Import-Module '$env:Windir\System32\WindowsPowerShell\v1.0\Modules\Defender\Defender.psd1'; Add-MpPreference -ExclusionPath '$(Convert-Path .)'" -Verb runAs
- }
- if ($Proxy -eq "") {$PSDefaultParameterValues.Remove("*:Proxy")}
- else {$PSDefaultParameterValues["*:Proxy"] = $Proxy}
- Update-Status("Initializing Variables...")
- $Variables | Add-Member -Force @{DecayStart = Get-Date}
- $Variables | Add-Member -Force @{DecayPeriod = 120} #seconds
- $Variables | Add-Member -Force @{DecayBase = 1 - 0.1} #decimal percentage
- $Variables | Add-Member -Force @{ActiveMinerPrograms = @()}
- $Variables | Add-Member -Force @{Miners = @()}
- #Start the log
- Start-Transcript -Path ".\Logs\miner.log" -Append -Force
- #Update stats with missing data and set to today's date/time
- if (Test-Path "Stats") {Get-ChildItemContent "Stats" | ForEach {$Stat = Set-Stat $_.Name $_.Content.Week}}
- #Set donation parameters
- $Variables | Add-Member -Force @{DonateRandom = [PSCustomObject]@{}}
- $Variables | Add-Member -Force @{LastDonated = (Get-Date).AddDays(-1).AddHours(1)}
- If ($Config.Donate -lt 3) {$Config.Donate = (0, (3..8)) | Get-Random}
- $Variables | Add-Member -Force @{WalletBackup = $Config.Wallet}
- $Variables | Add-Member -Force @{UserNameBackup = $Config.UserName}
- $Variables | Add-Member -Force @{WorkerNameBackup = $Config.WorkerName}
- $Variables | Add-Member -Force @{EarningsPool = ""}
- $Variables | Add-Member -Force @{BrainJobs = @()}
- $Variables | Add-Member -Force @{EarningsTrackerJobs = @()}
- $Variables | Add-Member -Force @{Earnings = @{}}
-
- $Location = $Config.Location
-
- # Find available TCP Ports
- $StartPort = 4068
- $Config.Type | sort | foreach {
- Update-Status("Finding available TCP Port for $($_)")
- $Port = Get-FreeTcpPort($StartPort)
- $Variables | Add-Member -Force @{"$($_)MinerAPITCPPort" = $Port}
- Update-Status("Miners API Port: $($Port)")
- $StartPort = $Port + 1
- }
- Sleep 2
-}
-
-Function Start-ChildJobs {
- # Starts Brains if necessary
- $Config.PoolName | foreach { if ($_ -notin $Variables.BrainJobs.PoolName) {
- $BrainPath = "$($Variables.MainPath)\BrainPlus\$($_)"
- $BrainName = (".\BrainPlus\" + $_ + "\BrainPlus.ps1")
- if (Test-Path $BrainName) {
- $Variables.StatusText = "Starting BrainPlus for $($_)..."
- $BrainJob = Start-Job -FilePath $BrainName -ArgumentList @($BrainPath)
- $BrainJob | Add-Member -Force @{PoolName = $_}
- $Variables.BrainJobs += $BrainJob
- rv BrainJob
- }
- }}
- # Starts Earnings Tracker Job if necessary
- $StartDelay = 0
- if ($Config.TrackEarnings) {
- $Config.PoolName | sort | foreach { if ($_ -notin $Variables.EarningsTrackerJobs.PoolName) {
- $Params = @{
- pool = $_
- Wallet =
- if ($_ -eq "miningpoolhub") {
- if ($Config.PoolsConfig.$_) {$Config.PoolsConfig.$_.APIKey}else {$Config.PoolsConfig.default.APIKey}
- }
- else {
- if ($Config.PoolsConfig.$_) {$Config.PoolsConfig.$_.Wallet}else {$Config.PoolsConfig.default.Wallet}
- }
- Interval = 3
- WorkingDirectory = ($Variables.MainPath)
- StartDelay = $StartDelay
- EnableLog = $Config.EnableEarningsTrackerLogs
- }
- $EarningsJob = Start-Job -FilePath .\EarningsTrackerJob.ps1 -ArgumentList $Params
- If ($EarningsJob) {
- $Variables.StatusText = "Starting Earnings Tracker for $($_)"
- $EarningsJob | Add-Member -Force @{PoolName = $_}
- $Variables.EarningsTrackerJobs += $EarningsJob
- rv EarningsJob
- # Delay Start when several instances to avoid conflicts.
- $StartDelay = $StartDelay + 10
- }
- }
- }
- }
-}
-
-Function NPMCycle {
- $CycleTime = Measure-Command -Expression {
- if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1"); "LoadedInclude" | out-host}
-
- $Variables | Add-Member -Force @{EndLoop = $False}
-
- $Variables.StatusText = "Starting Cycle"
- $DecayExponent = [int](((Get-Date) - $Variables.DecayStart).TotalSeconds / $Variables.DecayPeriod)
-
- # Ensure we get the hashrate for running miners prior looking for best miner
- $Variables.ActiveMinerPrograms | ForEach {
- if ($_.Process -eq $null -or $_.Process.HasExited) {
- if ($_.Status -eq "Running") {$_.Status = "Failed"}
- }
- else {
- # we don't want to store hashrates if we run less than $Config.StatsInterval sec
- $WasActive = [math]::Round(((Get-Date) - $_.Process.StartTime).TotalSeconds)
- if ($WasActive -ge $Config.StatsInterval) {
- $_.HashRate = 0
- $Miner_HashRates = $null
- if ($_.New) {$_.Benchmarked++}
- $Miner_HashRates = Get-HashRate $_.API $_.Port ($_.New -and $_.Benchmarked -lt 3)
- $_.HashRate = $Miner_HashRates | Select -First $_.Algorithms.Count
- if ($Miner_HashRates.Count -ge $_.Algorithms.Count) {
- for ($i = 0; $i -lt $_.Algorithms.Count; $i++) {
- $Stat = Set-Stat -Name "$($_.Name)_$($_.Algorithms | Select -Index $i)_HashRate" -Value ($Miner_HashRates | Select -Index $i)
- }
- $_.New = $false
- $_.Hashrate_Gathered = $true
- "Stats $($_.Algorithms) -> $($Miner_HashRates | ConvertTo-Hash) after $($WasActive) sec" | out-host
- }
- }
- }
- }
-
- #Activate or deactivate donation
- if ((Get-Date).AddDays(-1).AddMinutes($Config.Donate) -ge $Variables.LastDonated -and $Variables.DonateRandom.wallet -eq $Null) {
- # Get donation addresses randomly from agreed developers list
- # This will fairly distribute donations to Developers
- # Developers list and wallets is publicly available at: https://nemosminer.com/data/devlist.json
- try {$Donation = Invoke-WebRequest "https://nemosminer.com/data/devlist.json" -TimeoutSec 15 -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
- }
- catch {$Donation = @([PSCustomObject]@{Name = "mrplus"; Wallet = "134bw4oTorEJUUVFhokDQDfNqTs7rBMNYy"; UserName = "mrplus"}, [PSCustomObject]@{Name = "nemo"; Wallet = "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE"; UserName = "nemo"})
- }
- if ($Donation -ne $null) {
- If ($Config.Donate -lt 3) {$Config.Donate = (0, (3..8)) | Get-Random}
- $Variables.DonateRandom = $Donation | Get-Random
- $Config | Add-Member -Force @{PoolsConfig = [PSCustomObject]@{default = [PSCustomObject]@{Wallet = $Variables.DonateRandom.Wallet; UserName = $Variables.DonateRandom.UserName; WorkerName = "$($Variables.CurrentProduct)$($Variables.CurrentVersion.ToString().replace('.',''))"; PricePenaltyFactor = 1}}}
- }
- }
- if (((Get-Date).AddDays(-1) -ge $Variables.LastDonated -and $Variables.DonateRandom.Wallet -ne $Null) -or (! $Config.PoolsConfig)) {
- $Config | Add-Member -Force -MemberType ScriptProperty -Name "PoolsConfig" -Value {
- If (Test-Path ".\Config\PoolsConfig.json") {
- get-content ".\Config\PoolsConfig.json" | ConvertFrom-json
- }
- else {
- [PSCustomObject]@{default = [PSCustomObject]@{
- Wallet = "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE"
- UserName = "nemo"
- WorkerName = "NemosMinerNoCfg"
- PoolPenalty = 1
- }
- }
- }
- }
- $Variables.LastDonated = Get-Date
- $Variables.DonateRandom = [PSCustomObject]@{}
- }
- $Variables.StatusText = "Loading BTC rate from 'api.coinbase.com'.."
- $Rates = Invoke-RestMethod "https://api.coinbase.com/v2/exchange-rates?currency=BTC" -TimeoutSec 15 -UseBasicParsing | Select-Object -ExpandProperty data | Select-Object -ExpandProperty rates
- $Config.Currency | Where-Object {$Rates.$_} | ForEach-Object {$Rates | Add-Member $_ ([Double]$Rates.$_) -Force}
- $Variables | Add-Member -Force @{Rates = $Rates}
- #Load the Stats
- $Stats = [PSCustomObject]@{}
- if (Test-Path "Stats") {Get-ChildItemContent "Stats" | ForEach {$Stats | Add-Member $_.Name $_.Content}}
- #Load information about the Pools
- $Variables.StatusText = "Loading pool stats.."
- $PoolFilter = @()
- $Config.PoolName | foreach {$PoolFilter += ($_ += ".*")}
- Do {
- $AllPools = if (Test-Path "Pools") {Get-ChildItemContent "Pools" -Include $PoolFilter | ForEach {$_.Content | Add-Member @{Name = $_.Name} -PassThru} |
- Where {$_.SSL -EQ $Config.SSL -and ($Config.PoolName.Count -eq 0 -or ($_.Name -in $Config.PoolName)) -and (!$Config.Algorithm -or ((!($Config.Algorithm | ? {$_ -like "+*"}) -or $_.Algorithm -in ($Config.Algorithm | ? {$_ -like "+*"}).Replace("+", "")) -and (!($Config.Algorithm | ? {$_ -like "-*"}) -or $_.Algorithm -notin ($Config.Algorithm | ? {$_ -like "-*"}).Replace("-", ""))) )}
- }
- if ($AllPools.Count -eq 0) {
- $Variables.StatusText = "! Error contacting pool retrying in 30 seconds.."
- Sleep 30
- }
- } While ($AllPools.Count -eq 0)
- $Variables.StatusText = "Computing pool stats.."
- # Use location as preference and not the only one
- $LocPools = $AllPools | ? {$_.location -eq $Config.Location}
- $AllPools = $LocPools + ($AllPools | ? {$_.name -notin $LocPools.name})
- rv LocPools
- # Filter Algo based on Per Pool Config
- $PoolsConf = $Config.PoolsConfig
- $AllPools = $AllPools | Where {$_.Name -notin ($PoolsConf | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name) -or ($_.Name -in ($PoolsConf | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name) -and ((!($PoolsConf.($_.Name).Algorithm | ? {$_ -like "+*"}) -or ("+$($_.Algorithm)" -in $PoolsConf.($_.Name).Algorithm)) -and ("-$($_.Algorithm)" -notin $PoolsConf.($_.Name).Algorithm)))}
- # if($AllPools.Count -eq 0){$Variables.StatusText = "Error contacting pool, retrying.."; $timerCycle.Interval = 15000 ; $timerCycle.Start() ; return}
- $Pools = [PSCustomObject]@{}
- $Pools_Comparison = [PSCustomObject]@{}
- $AllPools.Algorithm | Sort -Unique | ForEach {
- $Pools | Add-Member $_ ($AllPools | Where Algorithm -EQ $_ | Sort Price -Descending | Select -First 1)
- $Pools_Comparison | Add-Member $_ ($AllPools | Where Algorithm -EQ $_ | Sort StablePrice -Descending | Select -First 1)
- }
- # $AllPools.Algorithm | Select -Unique | ForEach {$Pools_Comparison | Add-Member $_ ($AllPools | Where Algorithm -EQ $_ | Sort StablePrice -Descending | Select -First 1)}
- #Load information about the Miners
- #Messy...?
-
- # $Variables.StatusText = "Looking for Miners file changes.."
- if (!($Variables.MinersHash)) {
- If (Test-Path ".\Config\MinersHash.json") {
- $Variables.MinersHash = Get-Content ".\Config\MinersHash.json" | ConvertFrom-Json
- }
- else {
- $Variables.MinersHash = Get-ChildItem .\Miners\ -filter "*.ps1" | Get-FileHash
- $Variables.MinersHash | ConvertTo-Json | out-file ".\Config\MinersHash.json"
- }
- }
- else {
- Compare-Object $Variables.MinersHash (Get-ChildItem .\Miners\ -filter "*.ps1" | Get-FileHash) -Property "Hash", "Path" | Sort "Path" -Unique | % {
- $Variables.StatusText = "Miner Updated: $($_.Path)"
- $NewMiner = &$_.path
- $NewMiner | Add-Member -Force @{Name = (Get-Item $_.Path).BaseName}
- If (Test-Path (Split-Path $NewMiner.Path)) {
- $Variables.ActiveMinerPrograms | Where { $_.Status -eq "Running" -and $_.Path -eq (Resolve-Path $NewMiner.Path)} | ForEach {
- [Array]$filtered = ($BestMiners_Combo | Where Path -EQ $_.Path | Where Arguments -EQ $_.Arguments)
- if ($filtered.Count -eq 0) {
- if ($_.Process -eq $null) {
- $_.Status = "Failed"
- }
- elseif ($_.Process.HasExited -eq $false) {
- $_.Active += (Get-Date) - $_.Process.StartTime
- $_.Process.CloseMainWindow() | Out-Null
- Sleep 1
- # simply "Kill with power"
- Stop-Process $_.Process -Force | Out-Null
- $Variables.StatusText = "closing current miner for Update"
- Sleep 1
- $_.Status = "Idle"
- }
- #Restore Bias for non-active miners
- $Variables.Miners | Where Path -EQ $_.Path | Where Arguments -EQ $_.Arguments | ForEach {$_.Profit_Bias = $_.Profit_Bias_Orig}
- }
- }
- Get-ChildItem -path ".\stats\" -filter "$($NewMiner.Name)_*.txt" | Remove-Item -Force -Recurse
- Remove-Item -Force -Recurse (Split-Path $NewMiner.Path)
- }
- $Variables.MinersHash = Get-ChildItem .\Miners\ -filter "*.ps1" | Get-FileHash
- $Variables.MinersHash | ConvertTo-Json | out-file ".\Config\MinersHash.json"
- }
- }
-
- $Variables.StatusText = "Loading miners.."
- $Variables | Add-Member -Force @{Miners = @()}
- $StartPort = 4068
- $Variables.Miners = if (Test-Path "Miners") {
- @(
- if ($Config.IncludeRegularMiners -and (Test-Path "Miners")) {Get-ChildItemContent "Miners"}
- if ($Config.IncludeOptionalMiners -and (Test-Path "OptionalMiners")) {Get-ChildItemContent "OptionalMiners"}
- if (Test-Path "CustomMiners") { Get-ChildItemContent "CustomMiners"}
- ) | ForEach {$_.Content | Add-Member @{Name = $_.Name} -PassThru} |
- Where {$Config.Type.Count -eq 0 -or (Compare $Config.Type $_.Type -IncludeEqual -ExcludeDifferent | Measure).Count -gt 0} |
- Where {!($Config.Algorithm | ? {$_.StartsWith("+")}) -or (Compare (($Config.Algorithm | ? {$_.StartsWith("+")}).Replace("+", "")) $_.HashRates.PSObject.Properties.Name -IncludeEqual -ExcludeDifferent | Measure).Count -gt 0} |
- Where {$Config.MinerName.Count -eq 0 -or (Compare $Config.MinerName $_.Name -IncludeEqual -ExcludeDifferent | Measure).Count -gt 0}
- }
- $Variables.Miners = $Variables.Miners | ForEach {
- $Miner = $_
- if ((Test-Path $Miner.Path) -eq $false) {
- $Variables.StatusText = "Downloading $($Miner.Name).."
- if ((Split-Path $Miner.URI -Leaf) -eq (Split-Path $Miner.Path -Leaf)) {
- New-Item (Split-Path $Miner.Path) -ItemType "Directory" | Out-Null
- Invoke-WebRequest $Miner.URI -TimeoutSec 15 -OutFile $_.Path -UseBasicParsing
- }
- elseif (([IO.FileInfo](Split-Path $_.URI -Leaf)).Extension -eq '') {
- $Path_Old = Get-PSDrive -PSProvider FileSystem | ForEach {Get-ChildItem -Path $_.Root -Include (Split-Path $Miner.Path -Leaf) -Recurse -ErrorAction Ignore} | Sort LastWriteTimeUtc -Descending | Select -First 1
- $Path_New = $Miner.Path
-
- if ($Path_Old -ne $null) {
- if (Test-Path (Split-Path $Path_New)) {(Split-Path $Path_New) | Remove-Item -Recurse -Force}
- (Split-Path $Path_Old) | Copy-Item -Destination (Split-Path $Path_New) -Recurse -Force
- }
- else {
- $Variables.StatusText = "Cannot find $($Miner.Path) distributed at $($Miner.URI). "
- }
- }
- else {
- Expand-WebRequest $Miner.URI (Split-Path $Miner.Path)
- }
- }
- else {
- $Miner
- }
- }
- $Variables.StatusText = "Comparing miners and pools.."
- if ($Variables.Miners.Count -eq 0) {$Variables.StatusText = "No Miners!"}#; sleep $Config.Interval; continue}
-
- $Variables.Miners | ForEach {
- $Miner = $_
- $Miner_HashRates = [PSCustomObject]@{}
- $Miner_Pools = [PSCustomObject]@{}
- $Miner_Pools_Comparison = [PSCustomObject]@{}
- $Miner_Profits = [PSCustomObject]@{}
- $Miner_Profits_Comparison = [PSCustomObject]@{}
- $Miner_Profits_Bias = [PSCustomObject]@{}
- $Miner_Types = $Miner.Type | Select -Unique
- $Miner_Indexes = $Miner.Index | Select -Unique
- $Miner.HashRates | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
- $Miner_HashRates | Add-Member $_ ([Double]$Miner.HashRates.$_)
- $Miner_Pools | Add-Member $_ ([PSCustomObject]$Pools.$_)
- $Miner_Pools_Comparison | Add-Member $_ ([PSCustomObject]$Pools_Comparison.$_)
- $Miner_Profits | Add-Member $_ ([Double]$Miner.HashRates.$_ * $Pools.$_.Price)
- $Miner_Profits_Comparison | Add-Member $_ ([Double]$Miner.HashRates.$_ * $Pools_Comparison.$_.Price)
- $Miner_Profits_Bias | Add-Member $_ ([Double]$Miner.HashRates.$_ * $Pools.$_.Price * (1 - ($Config.MarginOfError * [Math]::Pow($Variables.DecayBase, $DecayExponent))))
- }
- $Miner_Profit = [Double]($Miner_Profits.PSObject.Properties.Value | Measure -Sum).Sum
- $Miner_Profit_Comparison = [Double]($Miner_Profits_Comparison.PSObject.Properties.Value | Measure -Sum).Sum
- $Miner_Profit_Bias = [Double]($Miner_Profits_Bias.PSObject.Properties.Value | Measure -Sum).Sum
- $Miner.HashRates | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
- if (-not [String]$Miner.HashRates.$_) {
- $Miner_HashRates.$_ = $null
- $Miner_Profits.$_ = $null
- $Miner_Profits_Comparison.$_ = $null
- $Miner_Profits_Bias.$_ = $null
- $Miner_Profit = $null
- $Miner_Profit_Comparison = $null
- $Miner_Profit_Bias = $null
- }
- }
- if ($Miner_Types -eq $null) {$Miner_Types = $Variables.Miners.Type | Select -Unique}
- if ($Miner_Indexes -eq $null) {$Miner_Indexes = $Variables.Miners.Index | Select -Unique}
- if ($Miner_Types -eq $null) {$Miner_Types = ""}
- if ($Miner_Indexes -eq $null) {$Miner_Indexes = 0}
- $Miner.HashRates = $Miner_HashRates
- $Miner | Add-Member Pools $Miner_Pools
- $Miner | Add-Member Profits $Miner_Profits
- $Miner | Add-Member Profits_Comparison $Miner_Profits_Comparison
- $Miner | Add-Member Profits_Bias $Miner_Profits_Bias
- $Miner | Add-Member Profit $Miner_Profit
- $Miner | Add-Member Profit_Comparison $Miner_Profit_Comparison
- $Miner | Add-Member Profit_Bias $Miner_Profit_Bias
- $Miner | Add-Member Profit_Bias_Orig $Miner_Profit_Bias
- $Miner | Add-Member Type $Miner_Types -Force
- $Miner | Add-Member Index $Miner_Indexes -Force
- $Miner.Path = Convert-Path $Miner.Path
- }
- $Variables.Miners | ForEach {
- $Miner = $_
- $Miner_Devices = $Miner.Device | Select -Unique
- if ($Miner_Devices -eq $null) {$Miner_Devices = ($Variables.Miners | Where {(Compare $Miner.Type $_.Type -IncludeEqual -ExcludeDifferent | Measure).Count -gt 0}).Device | Select -Unique}
- if ($Miner_Devices -eq $null) {$Miner_Devices = $Miner.Type}
- $Miner | Add-Member Device $Miner_Devices -Force
- }
- # Remove miners when no estimation info from pools or 0BTC. Avoids mining when algo down at pool or benchmarking for ever
- If (($Variables.Miners | ? {($_.Pools.PSObject.Properties.Value.Price -ne $null) -and ($_.Pools.PSObject.Properties.Value.Price -gt 0)}).Count -gt 0) {$Variables.Miners = $Variables.Miners | ? {($_.Pools.PSObject.Properties.Value.Price -ne $null) -and ($_.Pools.PSObject.Properties.Value.Price -gt 0)}}
-
- #Don't penalize active miners. Miner could switch a little bit later and we will restore his bias in this case
- $Variables.ActiveMinerPrograms | Where { $_.Status -eq "Running" } | ForEach {$Variables.Miners | Where Path -EQ $_.Path | Where Arguments -EQ $_.Arguments | ForEach {$_.Profit_Bias = $_.Profit * (1 + $Config.ActiveMinerGainPct / 100)}}
- #Get most profitable miner combination i.e. AMD+NVIDIA+CPU
- $BestMiners = $Variables.Miners | Select Type, Index -Unique | ForEach {$Miner_GPU = $_; ($Variables.Miners | Where {(Compare $Miner_GPU.Type $_.Type | Measure).Count -eq 0 -and (Compare $Miner_GPU.Index $_.Index | Measure).Count -eq 0} | Sort -Descending {($_ | Where Profit -EQ $null | Measure).Count}, {($_ | Measure Profit_Bias -Sum).Sum}, {($_ | Where Profit -NE 0 | Measure).Count} | Select -First 1)}
- $BestDeviceMiners = $Variables.Miners | Select Device -Unique | ForEach {$Miner_GPU = $_; ($Variables.Miners | Where {(Compare $Miner_GPU.Device $_.Device | Measure).Count -eq 0} | Sort -Descending {($_ | Where Profit -EQ $null | Measure).Count}, {($_ | Measure Profit_Bias -Sum).Sum}, {($_ | Where Profit -NE 0 | Measure).Count} | Select -First 1)}
- $BestMiners_Comparison = $Variables.Miners | Select Type, Index -Unique | ForEach {$Miner_GPU = $_; ($Variables.Miners | Where {(Compare $Miner_GPU.Type $_.Type | Measure).Count -eq 0 -and (Compare $Miner_GPU.Index $_.Index | Measure).Count -eq 0} | Sort -Descending {($_ | Where Profit -EQ $null | Measure).Count}, {($_ | Measure Profit_Comparison -Sum).Sum}, {($_ | Where Profit -NE 0 | Measure).Count} | Select -First 1)}
- $BestDeviceMiners_Comparison = $Variables.Miners | Select Device -Unique | ForEach {$Miner_GPU = $_; ($Variables.Miners | Where {(Compare $Miner_GPU.Device $_.Device | Measure).Count -eq 0} | Sort -Descending {($_ | Where Profit -EQ $null | Measure).Count}, {($_ | Measure Profit_Comparison -Sum).Sum}, {($_ | Where Profit -NE 0 | Measure).Count} | Select -First 1)}
- $Miners_Type_Combos = @([PSCustomObject]@{Combination = @()}) + (Get-Combination ($Variables.Miners | Select Type -Unique) | Where {(Compare ($_.Combination | Select -ExpandProperty Type -Unique) ($_.Combination | Select -ExpandProperty Type) | Measure).Count -eq 0})
- $Miners_Index_Combos = @([PSCustomObject]@{Combination = @()}) + (Get-Combination ($Variables.Miners | Select Index -Unique) | Where {(Compare ($_.Combination | Select -ExpandProperty Index -Unique) ($_.Combination | Select -ExpandProperty Index) | Measure).Count -eq 0})
- $Miners_Device_Combos = (Get-Combination ($Variables.Miners | Select Device -Unique) | Where {(Compare ($_.Combination | Select -ExpandProperty Device -Unique) ($_.Combination | Select -ExpandProperty Device) | Measure).Count -eq 0})
- $BestMiners_Combos = $Miners_Type_Combos | ForEach {$Miner_Type_Combo = $_.Combination; $Miners_Index_Combos | ForEach {$Miner_Index_Combo = $_.Combination; [PSCustomObject]@{Combination = $Miner_Type_Combo | ForEach {$Miner_Type_Count = $_.Type.Count; [Regex]$Miner_Type_Regex = '^(' + (($_.Type | ForEach {[Regex]::Escape($_)}) -join '|') + ')$'; $Miner_Index_Combo | ForEach {$Miner_Index_Count = $_.Index.Count; [Regex]$Miner_Index_Regex = '^(' + (($_.Index | ForEach {[Regex]::Escape($_)}) -join '|') + ')$'; $BestMiners | Where {([Array]$_.Type -notmatch $Miner_Type_Regex).Count -eq 0 -and ([Array]$_.Index -notmatch $Miner_Index_Regex).Count -eq 0 -and ([Array]$_.Type -match $Miner_Type_Regex).Count -eq $Miner_Type_Count -and ([Array]$_.Index -match $Miner_Index_Regex).Count -eq $Miner_Index_Count}}}}}}
- $BestMiners_Combos += $Miners_Device_Combos | ForEach {$Miner_Device_Combo = $_.Combination; [PSCustomObject]@{Combination = $Miner_Device_Combo | ForEach {$Miner_Device_Count = $_.Device.Count; [Regex]$Miner_Device_Regex = '^(' + (($_.Device | ForEach {[Regex]::Escape($_)}) -join '|') + ')$'; $BestDeviceMiners | Where {([Array]$_.Device -notmatch $Miner_Device_Regex).Count -eq 0 -and ([Array]$_.Device -match $Miner_Device_Regex).Count -eq $Miner_Device_Count}}}}
- $BestMiners_Combos_Comparison = $Miners_Type_Combos | ForEach {$Miner_Type_Combo = $_.Combination; $Miners_Index_Combos | ForEach {$Miner_Index_Combo = $_.Combination; [PSCustomObject]@{Combination = $Miner_Type_Combo | ForEach {$Miner_Type_Count = $_.Type.Count; [Regex]$Miner_Type_Regex = '^(' + (($_.Type | ForEach {[Regex]::Escape($_)}) -join '|') + ')$'; $Miner_Index_Combo | ForEach {$Miner_Index_Count = $_.Index.Count; [Regex]$Miner_Index_Regex = '^(' + (($_.Index | ForEach {[Regex]::Escape($_)}) -join '|') + ')$'; $BestMiners_Comparison | Where {([Array]$_.Type -notmatch $Miner_Type_Regex).Count -eq 0 -and ([Array]$_.Index -notmatch $Miner_Index_Regex).Count -eq 0 -and ([Array]$_.Type -match $Miner_Type_Regex).Count -eq $Miner_Type_Count -and ([Array]$_.Index -match $Miner_Index_Regex).Count -eq $Miner_Index_Count}}}}}}
- $BestMiners_Combos_Comparison += $Miners_Device_Combos | ForEach {$Miner_Device_Combo = $_.Combination; [PSCustomObject]@{Combination = $Miner_Device_Combo | ForEach {$Miner_Device_Count = $_.Device.Count; [Regex]$Miner_Device_Regex = '^(' + (($_.Device | ForEach {[Regex]::Escape($_)}) -join '|') + ')$'; $BestDeviceMiners_Comparison | Where {([Array]$_.Device -notmatch $Miner_Device_Regex).Count -eq 0 -and ([Array]$_.Device -match $Miner_Device_Regex).Count -eq $Miner_Device_Count}}}}
- $BestMiners_Combo = $BestMiners_Combos | Sort -Descending {($_.Combination | Where Profit -EQ $null | Measure).Count}, {($_.Combination | Measure Profit_Bias -Sum).Sum}, {($_.Combination | Where Profit -NE 0 | Measure).Count} | Select -First 1 | Select -ExpandProperty Combination
- $BestMiners_Combo_Comparison = $BestMiners_Combos_Comparison | Sort -Descending {($_.Combination | Where Profit -EQ $null | Measure).Count}, {($_.Combination | Measure Profit_Comparison -Sum).Sum}, {($_.Combination | Where Profit -NE 0 | Measure).Count} | Select -First 1 | Select -ExpandProperty Combination
-
- # No CPU mining if GPU miner prevents it
- If ($BestMiners_Combo.PreventCPUMining -contains $true) {
- $BestMiners_Combo = $BestMiners_Combo | ? {$_.type -ne "CPU"}
- $Variables.StatusText = "Miner prevents CPU mining"
- }
-
- # Ban miners if too many failures as defined by MaxMinerFailure
- # 0 means no ban
- # Int value means ban after x failures
- # defaults to 3 if no value in config
- # ** Ban is not persistent across sessions **
- # If ($Config.MaxMinerFailure -gt 0){
- # $Config | Add-Member -Force @{ MaxMinerFailure = If ($Config.MaxMinerFailure) {$Config.MaxMinerFailure} else {3} }
- # $Config.MaxMinerFailure = If ($Config.MaxMinerFailure) {$Config.MaxMinerFailure} else {3}
- # $BannedMiners = $Variables.ActiveMinerPrograms | Where { $_.Status -eq "Failed" -and $_.Activated -ge $Config.MaxMinerFailure }
- # $BannedMiners | foreach { $Variables.StatusText = "BANNED: $($_.Name) / $($_.Algorithms). Too many failures. Consider Algo exclusion in config." }
- # $BestMiners_Combo = $BestMiners_Combo | Where { $_.Path -notin $BannedMiners.Path -and $_.Arguments -notin $BannedMiners.Arguments }
- # }
-
- #Add the most profitable miners to the active list
- $BestMiners_Combo | ForEach {
- if (($Variables.ActiveMinerPrograms | Where Path -EQ $_.Path | Where Arguments -EQ $_.Arguments).Count -eq 0) {
- $Variables.ActiveMinerPrograms += [PSCustomObject]@{
- Type = $_.Type
- Name = $_.Name
- Path = $_.Path
- Arguments = $_.Arguments
- Wrap = $_.Wrap
- Process = $null
- API = $_.API
- Port = $_.Port
- Algorithms = $_.HashRates.PSObject.Properties.Name
- New = $false
- Active = [TimeSpan]0
- TotalActive = [TimeSpan]0
- Activated = 0
- Status = "Idle"
- HashRate = 0
- Benchmarked = 0
- Hashrate_Gathered = ($_.HashRates.PSObject.Properties.Value -ne $null)
- User = $_.User
- Host = $_.Host
- Coin = $_.Coin
- }
- }
- }
- #Stop or start miners in the active list depending on if they are the most profitable
- # We have to stop processes first or the port would be busy
- $Variables.ActiveMinerPrograms | ForEach {
- [Array]$filtered = ($BestMiners_Combo | Where Path -EQ $_.Path | Where Arguments -EQ $_.Arguments)
- if ($filtered.Count -eq 0) {
- if ($_.Process -eq $null) {
- $_.Status = "Failed"
- # Try to kill any process with the same path, in case it is still running but the process handle is incorrect
- $KillPath = $_.Path
- Get-Process | Where-Object {$_.Path -eq $KillPath} | Stop-Process -Force
- }
- elseif ($_.Process.HasExited -eq $false) {
- $_.Process.CloseMainWindow() | Out-Null
- Sleep 1
- # simply "Kill with power"
- Stop-Process $_.Process -Force | Out-Null
- Sleep 1
- # Kill any process with the same path, in case $_.Process is incorrect
- $KillPath = $_.Path
- Get-Process | Where-Object {$_.Path -eq $KillPath} | Stop-Process -Force
- $Variables.StatusText = "closing current miner and switching"
- Sleep 1
- $_.Status = "Idle"
- }
- #Restore Bias for non-active miners
- $Variables.Miners | Where Path -EQ $_.Path | Where Arguments -EQ $_.Arguments | ForEach {$_.Profit_Bias = $_.Profit_Bias_Orig}
- }
- }
- $newMiner = $false
- $CurrentMinerHashrate_Gathered = $false
- $newMiner = $false
- $CurrentMinerHashrate_Gathered = $false
- $Variables.ActiveMinerPrograms | ForEach {
- [Array]$filtered = ($BestMiners_Combo | Where Path -EQ $_.Path | Where Arguments -EQ $_.Arguments)
- if ($filtered.Count -gt 0) {
- if ($_.Process -eq $null -or $_.Process.HasExited -ne $false) {
- # Log switching information to .\log\swicthing.log
- [pscustomobject]@{date = (get-date); Type = $_.Type; algo = $_.Algorithms; wallet = $_.User; username = $Config.UserName; Host = $_.host} | export-csv .\Logs\switching.log -Append -NoTypeInformation
-
- # Launch prerun if exists
- If ($_.Type -ne "CPU") {
- $PrerunName = ".\Prerun\" + $_.Algorithms + ".bat"
- $DefaultPrerunName = ".\Prerun\default.bat"
- If (Test-Path $PrerunName) {
- Update-Status("Launching Prerun: $PrerunName")
- Start-Process $PrerunName -WorkingDirectory ".\Prerun" -WindowStyle hidden
- Sleep 2
- }
- else {
- If (Test-Path $DefaultPrerunName) {
- $Variables.StatusText = "Launching Prerun: $PrerunName"
- Start-Process $DefaultPrerunName -WorkingDirectory ".\Prerun" -WindowStyle hidden
- Sleep 2
- }
- }
- }
-
- Sleep $Config.Delay #Wait to prevent BSOD
- $Variables.StatusText = "Starting miner"
- $Variables.DecayStart = Get-Date
- $_.New = $true
- $_.Activated++
- # if ($_.Process -ne $null) {$_.Active += $_.Process.ExitTime - $_.Process.StartTime}
- if ($_.Wrap) {$_.Process = Start-Process -FilePath "PowerShell" -ArgumentList "-WindowStyle Minimized -executionpolicy bypass -command . '$(Convert-Path ".\Wrapper.ps1")' -ControllerProcessID $PID -Id '$($_.Port)' -FilePath '$($_.Path)' -ArgumentList '$($_.Arguments)' -WorkingDirectory '$(Split-Path $_.Path)'" -PassThru}
- else {$_.Process = Start-SubProcess -FilePath $_.Path -ArgumentList $_.Arguments -WorkingDirectory (Split-Path $_.Path)}
- if ($_.Process -eq $null) {$_.Status = "Failed"}
- else {
- $_.Status = "Running"
- $newMiner = $true
- #Newely started miner should looks better than other in the first run too
- $Variables.Miners | Where Path -EQ $_.Path | Where Arguments -EQ $_.Arguments | ForEach {$_.Profit_Bias = $_.Profit * (1 + $Config.ActiveMinerGainPct / 100)}
- }
- }
- else {
- $now = Get-Date
- $_.TotalActive = $_.TotalActive + ( $Now - $_.Process.StartTime ) - $_.Active
- $_.Active = $Now - $_.Process.StartTime
- }
- $CurrentMinerHashrate_Gathered = $_.Hashrate_Gathered
- }
- }
- #Do nothing for a few seconds as to not overload the APIs
- if ($newMiner -eq $true) {
- if ($Config.Interval -ge $Config.FirstInterval -and $Config.Interval -ge $Config.StatsInterval) { $Variables.TimeToSleep = $Config.Interval }
- else {
- if ($CurrentMinerHashrate_Gathered -eq $true) { $Variables.TimeToSleep = $Config.FirstInterval }
- else { $Variables.TimeToSleep = $Config.StatsInterval }
- }
- }
- else {
- $Variables.TimeToSleep = $Config.Interval
- }
- "--------------------------------------------------------------------------------" | out-host
- #Do nothing for a few seconds as to not overload the APIs
- if ($newMiner -eq $true) {
- if ($Config.Interval -ge $Config.FirstInterval -and $Config.Interval -ge $Config.StatsInterval) { $Variables.TimeToSleep = $Config.Interval }
- else {
- if ($CurrentMinerHashrate_Gathered -eq $true) { $Variables.TimeToSleep = $Config.FirstInterval }
- else { $Variables.TimeToSleep = $Config.StatsInterval }
- }
- }
- else {
- $Variables.TimeToSleep = $Config.Interval
- }
- #Save current hash rates
- $Variables.ActiveMinerPrograms | ForEach {
- if ($_.Process -eq $null -or $_.Process.HasExited) {
- if ($_.Status -eq "Running") {$_.Status = "Failed"}
- }
- else {
- # we don't want to store hashrates if we run less than $Config.StatsInterval sec
- $WasActive = [math]::Round(((Get-Date) - $_.Process.StartTime).TotalSeconds)
- if ($WasActive -ge $Config.StatsInterval) {
- $_.HashRate = 0
- $Miner_HashRates = $null
- if ($_.New) {$_.Benchmarked++}
- $Miner_HashRates = Get-HashRate $_.API $_.Port ($_.New -and $_.Benchmarked -lt 3)
- $_.HashRate = $Miner_HashRates | Select -First $_.Algorithms.Count
- if ($Miner_HashRates.Count -ge $_.Algorithms.Count) {
- for ($i = 0; $i -lt $_.Algorithms.Count; $i++) {
- $Stat = Set-Stat -Name "$($_.Name)_$($_.Algorithms | Select -Index $i)_HashRate" -Value ($Miner_HashRates | Select -Index $i)
- }
- $_.New = $false
- $_.Hashrate_Gathered = $true
- "Stats $($_.Algorithms) -> $($Miner_HashRates | ConvertTo-Hash) after $($WasActive) sec" | out-host
- }
- }
- }
- #Benchmark timeout
- # if($_.Benchmarked -ge 6 -or ($_.Benchmarked -ge 2 -and $_.Activated -ge 2))
- # {
- # for($i = 0; $i -lt $_.Algorithms.Count; $i++)
- # {
- # if((Get-Stat "$($_.Name)_$($_.Algorithms | Select -Index $i)_HashRate") -eq $null)
- # {
- # $Stat = Set-Stat -Name "$($_.Name)_$($_.Algorithms | Select -Index $i)_HashRate" -Value 0
- # }
- # }
- # }
- }
- # }
-
- <#
- For some reason (need to investigate) $Variables.ActiveMinerPrograms.psobject.TypeNames
- Inflates adding several lines at each loop and causing a memory leak after log runtime
- Code below copies the object which results in a new version which avoid the problem.
- Will need rework.
- #>
- $Variables.ActiveMinerPrograms | Where {$_.Status -ne "Running"} | foreach {$_.process = $_.process | select HasExited, StartTime, ExitTime}
- $ActiveMinerProgramsCOPY = @()
- $Variables.ActiveMinerPrograms | % {$ActiveMinerCOPY = [PSCustomObject]@{}; $_.psobject.properties | sort Name | % {$ActiveMinerCOPY | Add-Member -Force @{$_.Name = $_.Value}}; $ActiveMinerProgramsCOPY += $ActiveMinerCOPY}
- $Variables.ActiveMinerPrograms = $ActiveMinerProgramsCOPY
- rv ActiveMinerProgramsCOPY
- rv ActiveMinerCOPY
-
- $Error.Clear()
- $Global:Error.clear()
-
- Get-Job | ? {$_.State -eq "Completed"} | Remove-Job
- if ($Variables.BrainJobs.count -gt 0) {
- $Variables.BrainJobs | % {$_.ChildJobs | % {$_.Error.Clear()}}
- $Variables.BrainJobs | % {$_.ChildJobs | % {$_.Progress.Clear()}}
- $Variables.BrainJobs.ChildJobs | % {$_.Output.Clear()}
- }
- if ($Variables.EarningsTrackerJobs.count -gt 0) {
- $Variables.EarningsTrackerJobs | % {$_.ChildJobs | % {$_.Error.Clear()}}
- $Variables.EarningsTrackerJobs | % {$_.ChildJobs | % {$_.Progress.Clear()}}
- $Variables.EarningsTrackerJobs.ChildJobs | % {$_.Output.Clear()}
- }
-
- # Mostly used for debug. Will execute code found in .\EndLoopCode.ps1 if exists.
- if (Test-Path ".\EndLoopCode.ps1") {Invoke-Expression (Get-Content ".\EndLoopCode.ps1" -Raw)}
- }
- #$Variables.StatusText = "Cycle Time (seconds): $($CycleTime.TotalSeconds)"
- "Cycle Time (seconds): $($CycleTime.TotalSeconds)" | out-host
- $Variables | Add-Member -Force @{EndLoop = $True}
- $Variables.StatusText = "Sleeping $($Variables.TimeToSleep)"
- # Sleep $Variables.TimeToSleep
- # }
-}
-#Stop the log
-# Stop-Transcript
diff --git a/Data/Algorithms.json b/Data/Algorithms.json
new file mode 100644
index 0000000000..2ba8b9ae00
--- /dev/null
+++ b/Data/Algorithms.json
@@ -0,0 +1,228 @@
+{
+ "aeternity": "Cuckoo29",
+ "alephium": "Blake3",
+ "arctichash": "ArcticHash",
+ "argon2chukwa": "Argon2Chukwa",
+ "argon2chukwav2": "Argon2ChukwaV2",
+ "argon2d16000": "Argon2d16000",
+ "argon2d500": "Argon2dDyn",
+ "argon2ddyn": "Argon2dDyn",
+ "argon2wkrz": "Argon2WKZR",
+ "astralhash": "AstralHash",
+ "autolykos": "Autolykos2",
+ "bcd": "BCD",
+ "beamv2": "BeamV2",
+ "beamv3": "BeamV3",
+ "bfc": "Cuckaroo29bfc",
+ "binariumv1": "BinariumV1",
+ "bitcore": "MegaBtx",
+ "bittube": "Cuckaroo29B",
+ "bl2bsha3": "Blake2Bsha3",
+ "blake2bbtcc": "Blake2bBtcc",
+ "blake2bglt": "Blake2bGlt",
+ "blake2bsha3": "Blake2bSha3",
+ "chainox": "0x10",
+ "chukwa": "Argon2Chukwa",
+ "chukwav2": "ArgonChukwaV2",
+ "circcash": "CircCash",
+ "conflux": "Octopus",
+ "cortex": "Cuckaroo30CTX",
+ "cosacoin": "Cosa",
+ "cpupower": "CpuPower",
+ "cryptonight7": "CryptonightV1",
+ "cryptonight8": "CryptonightV2",
+ "cryptonightbbc": "CryptonightBbc",
+ "cryptonightcache": "CryptonightCache",
+ "cryptonightcatalans": "CryptonightCatalans",
+ "cryptonightccx": "CryptonightCcx",
+ "cryptonightconceal": "CryptonightCcx",
+ "cryptonightdouble": "CryptonightDouble",
+ "cryptonightfast": "CryptonightFast",
+ "cryptonightfast2": "CryptonightHalf",
+ "cryptonightgpu": "CryptonightGpu",
+ "cryptonighthalf": "CryptonightHalf",
+ "cryptonighthaven": "CryptonightXhv",
+ "cryptonightheavy": "CryptonightHeavy",
+ "cryptonightheavyhaven": "CryptonightXhv",
+ "cryptonightheavytube": "CryptonightHeavyTube",
+ "cryptonightheavyx": "CryptonightDouble",
+ "cryptonightlite": "CryptonightLite",
+ "cryptonightlitev7": "CryptonightLiteV1",
+ "cryptonightlitev7xor": "CryptonightLiteIpbc",
+ "cryptonightmasari": "CryptonightMsr",
+ "cryptonightmonero": "RandomX",
+ "cryptonightr": "CryptonightR",
+ "cryptonightrwz": "CryptonightRwz",
+ "cryptonightsaber": "CryptonightHeavyTube",
+ "cryptonighttlo": "CryptonightTlo",
+ "cryptonightturtle": "CryptonightTurtle",
+ "cryptonightupx": "CryptonightUpx",
+ "cryptonightv7": "CryptonightV1",
+ "cryptonightv8": "CryptonightV2",
+ "cryptonightv8reversewaltz": "CryptonightRwz",
+ "cryptonightv8zelerius": "CryptonightZls",
+ "cryptonightwow": "CryptonightWow",
+ "cryptonightxeq": "CryptonightXeq",
+ "cryptonightxhv": "CryptonightXhv",
+ "cryptonightzelerius": "CryptonightZls",
+ "cryptonightzls": "CryptonightZls",
+ "cuckaroo29-48": "Cuckaroo2948",
+ "cuckaroo29b": "Cuckaroo29B",
+ "cuckaroo29d": "CuckarooD29",
+ "cuckaroo29m": "CuckarooM29",
+ "cuckaroo29s": "Cuckaroo29S",
+ "cuckarood": "CuckarooD29",
+ "cuckarood29": "CuckarooD29",
+ "cuckarood29v": "CuckarooD29V",
+ "cuckaroom": "CuckarooM29",
+ "cuckaroom29": "CuckarooM29",
+ "cuckarooz": "CuckarooZ29",
+ "cuckarooz29": "CuckarooZ29",
+ "cuckoobfc": "Cuckaroo29bfc",
+ "cuckoocycle": "Cuckoo29",
+ "curve": "CurveHash",
+ "curvehash": "CurveHash",
+ "dagger": "Xdag",
+ "daggerhashimoto": "Ethash",
+ "dero": "AstroBWTV2",
+ "dynamo": "DynamoCoin",
+ "equihash125": "Equihash1254",
+ "equihash144": "Equihash1445",
+ "equihash192": "Equihash1927",
+ "equihash210": "Equihash2109",
+ "equihash96": "Equihash965",
+ "equihashbtg": "EquihashBTG",
+ "equihashzcl": "EquihashZCL",
+ "ergo": "Autolykos2",
+ "etc": "EtcHash",
+ "etchash": "EtcHash",
+ "eth": "Ethash",
+ "ethashlowmem": "EthashLowMem",
+ "ethashlowmemory": "EthashLowMem",
+ "firo": "FiroPoW",
+ "firopow": "FiroPoW",
+ "graft": "RandomGrft",
+ "grincuckaroo29": "Cuckaroo29",
+ "grincuckarood29": "CuckarooD29",
+ "grincuckatoo31": "Cuckatoo31",
+ "grincuckatoo32": "Cuckatoo32",
+ "heavyhash": "HeavyHash",
+ "hns": "Handshake",
+ "italocoin": "Cuckaroo2948",
+ "jeonghash": "JeongHash",
+ "k12": "Kangaroo",
+ "kangaroo12": "Kangaroo",
+ "kawpow": "KawPoW",
+ "keccakc": "KeccakC",
+ "komodo": "Equihash",
+ "lux": "Rx2",
+ "luxcoin": "Rx2",
+ "luxcore": "Rx2",
+ "lyra2": "Lyra2RE",
+ "lyra2h": "Lyra2h",
+ "lyra2re": "Lyra2RE",
+ "lyra2re2": "Lyra2RE2",
+ "lyra2re3": "Lyra2RE3",
+ "lyra2rev2": "Lyra2RE2",
+ "lyra2rev3": "Lyra2RE3",
+ "lyra2tdc": "Lyra2TDC",
+ "lyra2v2": "Lyra2RE2",
+ "lyra2v2webchain": "Lyra2v2Webchain",
+ "lyra2v3": "Lyra2RE3",
+ "lyra2z": "Lyra2Z",
+ "m7m": "m7m",
+ "megabtx": "MegaBtx",
+ "megamec": "MegaMec",
+ "minotaurx": "MinotaurX",
+ "monerov": "CuckarooD29V",
+ "mtp": "MTP",
+ "myrgr": "MyriadGroestl",
+ "myriadgroestl": "MyriadGroestl",
+ "neoscrypt": "Neoscrypt",
+ "neoscryptxaya": "NeoscryptXaya",
+ "obtc": "HeavyHash",
+ "padihash": "PadiHash",
+ "pawelhash": "PawelHash",
+ "phi2lux": "Phi2",
+ "power": "Yespower",
+ "power2b": "Yespower2b",
+ "poweric": "YespowerIc",
+ "poweriots": "Yespoweriots",
+ "poweritc": "YespowerItc",
+ "powerlitb": "YespowerLitb",
+ "powerltncg": "YespowerLtncg",
+ "powerr16": "YespowerR16",
+ "powerr32": "YespowerR32",
+ "powerr8": "YespowerR8",
+ "powerres": "YespowerRes",
+ "powersugar": "YespowerSugar",
+ "powertide": "YespowerTide",
+ "powerurx": "YespowerUrx",
+ "progpow": "ProgPoW",
+ "progpowepic": "ProgPoWEpic",
+ "progpowsero": "ProgPoWSero",
+ "progpowveil": "ProgPoWVeil",
+ "progpowveriblock": "ProgPoWVeriblock",
+ "progpowzano": "ProgPoWZano",
+ "qogecoin": "QogeCoin",
+ "rainforestv2": "RainforestV2",
+ "randomarq": "RandomxArq",
+ "randomepic": "RandomxEpic",
+ "randomgrft": "RandomGrft",
+ "randomhash2": "RandomHash2",
+ "randomkeva": "RandomxKeva",
+ "randoml": "RandomL",
+ "randomloki": "RandomxLoki",
+ "randomsfx": "RandomxSfx",
+ "randomwow": "RandomxWow",
+ "randomx": "RandomX",
+ "randomxl": "RandomxL",
+ "randomxloki": "RandomxLoki",
+ "randomxmonero": "RandomX",
+ "randomyada": "RandomYada",
+ "raptoreum": "Ghostrider",
+ "raven": "KawPoW",
+ "ravencoin": "KawPoW",
+ "rfv2": "RainforestV2",
+ "scala": "Panthera",
+ "scryptn11": "ScryptN11",
+ "scryptn2": "ScryptN2",
+ "sha256asicboost": "SHA256AsicBoost",
+ "sha256csm": "SHA256csm",
+ "skunk": "SkunkHash",
+ "swap": "Cuckaroo29S",
+ "theopennetwork": "SHA256ton",
+ "toncoin": "SHA256ton",
+ "tonpow": "SHA256ton",
+ "ubqhash": "UbqHash",
+ "verthash": "VertHash",
+ "verus": "VerusHash",
+ "verushash": "VerusHash",
+ "wildkeccak": "WildKeccak",
+ "wkrz": "Argon2Chukwa",
+ "xaya": "NeoScryptXaya",
+ "xla": "Panthera",
+ "yescryptr16": "YescryptR16",
+ "yescryptr32": "YescryptR32",
+ "yescryptr8": "YescryptR8",
+ "yescryptr8g": "YescryptR8g",
+ "yespower": "Yespower",
+ "yespower2b": "Yespower2b",
+ "yespowerarwn": "YespowerARWN",
+ "yespoweric": "YespowerIc",
+ "yespoweriots": "Yespoweriots",
+ "yespoweritc": "YespowerItc",
+ "yespowerlitb": "YespowerLitb",
+ "yespowerltncg": "YespowerLtncg",
+ "yespowerr16": "YespowerR16",
+ "yespowerr32": "YespowerR32",
+ "yespowerr8": "YespowerR8",
+ "yespowerres": "YespowerRes",
+ "yespowersugar": "YespowerSugar",
+ "yespowertide": "YespowerTide",
+ "yespowerurx": "YespowerUrx",
+ "zelantus": "KawPoW",
+ "zelhash": "Equihash1254",
+ "zcash": "Equihash",
+ "zhash": "EquihashBTG"
+}
\ No newline at end of file
diff --git a/Data/CoinNames.json b/Data/CoinNames.json
new file mode 100644
index 0000000000..5bdcdb613d
--- /dev/null
+++ b/Data/CoinNames.json
@@ -0,0 +1,569 @@
+{
+ "$PAC": "Paccoin",
+ "ABS": "Absolute",
+ "ABY": "Artbyte",
+ "ACM": "Actinium",
+ "ACP": "Anarchistsprime",
+ "ADOT": "Alterdot",
+ "ADZ": "AdzCoin",
+ "AE": "Aeternity",
+ "AEON": "Aeon",
+ "AEX": "Aeriumx",
+ "AGM": "Argoneum",
+ "AIB": "Advanced Internet Blocks",
+ "AION": "Aion",
+ "AKA": "Akroma",
+ "ALEX": "Alexandrite",
+ "ALTEX": "Altex",
+ "ANDS": "Anodos",
+ "ANI": "Anime",
+ "ANON": "Anon",
+ "ARC": "ArcticCoin",
+ "ARG": "Argentum",
+ "ARION": "Arion",
+ "ARQ": "Arqma",
+ "ARRR": "Piratechain",
+ "ARW": "Arrow",
+ "ARWN": "ArowanaCoin",
+ "ATH": "Atheios",
+ "ATOM": "Atomis",
+ "ATOMI": "Atomi",
+ "AUR": "Aurora",
+ "AURA": "Aura",
+ "AUS": "AustraliaCash",
+ "AVN": "Avian",
+ "AXE": "Axe",
+ "AYA": "AryaCoin",
+ "AZART": "Azart",
+ "B2G": "Bitcoin2gen",
+ "BBC": "BBC Coin",
+ "BBR": "Boolberry",
+ "BCA": "Atom",
+ "BCD": "BitDiamond",
+ "BCH": "BitcoinCash",
+ "BCHABC": "BitcoinCash ABC",
+ "BCHSV": "BitcoinCash SV",
+ "BCI": "BitcoinInterest",
+ "BCN": "ByteCoin",
+ "BCRS": "BitCreds",
+ "BCX": "BitcoinFlex",
+ "BEAM": "Beam",
+ "BELL": "BellCoin",
+ "BET": "BetaCoin",
+ "BFC": "Bitfree Cash",
+ "BGL": "Bitgesell",
+ "BHD": "Bithold",
+ "BIN": "Binarium",
+ "BITC": "BitCash",
+ "BLAS": "Blakestar2",
+ "BLAST": "Blast",
+ "BLOC": "Bloc",
+ "BNODE": "Beenode",
+ "BOLI": "Bolivar",
+ "BRAZ": "Brazio",
+ "BSD": "Bitsend",
+ "BSF": "BitcoinSF",
+ "BSHA3": "Bsha3",
+ "BST": "Blockstamp",
+ "BSTY": "Globalboost",
+ "BSV": "Bitcoin SV",
+ "BTA": "Bata",
+ "BTB": "Bitbar",
+ "BTC": "Bitcoin",
+ "BTCHP": "Betchip",
+ "BTCP": "BitcoinPrivate",
+ "BTCZ": "Bitcoinz",
+ "BTE": "Bitweb",
+ "BTG": "BitcoinGold",
+ "BTH": "Bithereum",
+ "BTM": "BTM",
+ "BTX": "Bitcore",
+ "BUCK": "Buck",
+ "BUEN": "Buenos",
+ "BUT": "ButKoin",
+ "BUTK": "ButKoin",
+ "BVG": "BitcoinVG",
+ "BXT": "BitToken",
+ "BZE": "Bzedge",
+ "BZL": "BzlCoin",
+ "BZX": "Bitcoin Zero",
+ "CANN": "CannabisCoin",
+ "CAT": "CatalansCoin",
+ "CBE": "Combode",
+ "CBS": "Cerberus",
+ "CCX": "Conceal",
+ "CFX": "Conflux",
+ "CHC": "ChainCoin",
+ "CHEESE": "CheeseCoin",
+ "CHI": "Xaya",
+ "CHOX": "Chainox",
+ "CHTA": "CheetahCoin",
+ "CICO": "Coinicles",
+ "CIRC": "CircCash",
+ "CKB": "Nervos",
+ "CKBTEST": "Nervos Testnet",
+ "CLO": "Callisto",
+ "CMM": "Commercium",
+ "CNOTE": "C-Note",
+ "COSA": "Cosanta",
+ "CPMK": "Chipmonk",
+ "CPU": "Cpuchain",
+ "CRDS": "Credits",
+ "CRM": "CREAM",
+ "CRP": "Cranepay",
+ "CRS": "Criptoreal",
+ "CSM": "Consortium",
+ "CTXC": "Cortex",
+ "CURVE": "CurvehashCoin",
+ "CXC": "CryptroxCoin",
+ "CXT": "Coinonat",
+ "D": "Denarius",
+ "DANE": "Danecoin",
+ "DASH": "Dash",
+ "DBIX": "DubaiCoin",
+ "DCR": "Decred",
+ "DEFIS": "Defis",
+ "DEFT": "Deft",
+ "DEM": "Emark",
+ "DERO": "Dero",
+ "DGB": "Digibyte",
+ "DGBODO": "Digibyte",
+ "DGC": "DigitalCoin",
+ "DIME": "DimeCoin",
+ "DIN": "Dinero",
+ "DMS": "Documentchain",
+ "DNGR": "DangerCoin",
+ "DOGE": "DogeCoin",
+ "DOGX": "Dogethereum",
+ "DSR": "Desire",
+ "DUO": "ParallelCoin",
+ "DVS": "Davies",
+ "DVT": "Devault",
+ "DYN": "Dynamic",
+ "DYNAMO": "DynamoCoin",
+ "EFL": "Egulden",
+ "EGEM": "EtherGem",
+ "ELI": "Eli",
+ "ELLA": "Ellaism",
+ "EMC2": "Einsteinium",
+ "EMD": "Emerald Crypto",
+ "EMRALS": "Emrals",
+ "ENCO": "Block Masters Stealth",
+ "EPIC": "EpicCash",
+ "EQT": "Equitrade",
+ "ERC": "EuropeCoin",
+ "ERE": "Ethercore",
+ "ERG": "Ergo",
+ "ESN": "EtherSocial",
+ "ESP": "Espers",
+ "ETC": "Ethereum Classic",
+ "ETCC": "EtherCC",
+ "ETH": "Ethereum",
+ "ETHO": "Ether1",
+ "ETN": "Electroneum",
+ "ETP": "Metaverse",
+ "ETZ": "EtherZero",
+ "EUNO": "Euno",
+ "EVO": "Coinevo",
+ "EVOX": "Evolution",
+ "EXO": "Exosis",
+ "EXP": "Expanse",
+ "FCH": "FreeCash",
+ "FIRO": "Firo",
+ "FJC": "FujiCoin",
+ "FLM": "Folm",
+ "FLO": "FlorinCoin",
+ "FLUX": "Flux",
+ "FOXD": "FoxDcoin",
+ "FTC": "FeatherCoin",
+ "FTO": "Futuro",
+ "FXC": "Fexchange",
+ "FXTC": "FxtcCoin",
+ "GALE": "GalleonCoin",
+ "GAME": "Gamecredits",
+ "GAP": "GapCoin",
+ "GATE": "GateCoin",
+ "GBX": "Gobyte",
+ "GCN": "GCoin",
+ "GEERT": "GeertCoin",
+ "GEN": "Genom",
+ "GENIX": "Genix",
+ "GENX": "Genesis",
+ "GEX": "Gexan",
+ "GIN": "Gin",
+ "GIO": "GravioCoin",
+ "GLC": "GoldCoin",
+ "GLD": "GoldCoin",
+ "GLEEC": "Gleec",
+ "GLT": "GlobalToken",
+ "GMC": "Grandmaster",
+ "GNTL": "GNTLCoin",
+ "GOL": "Goldiam",
+ "GOLD": "GoldCash",
+ "GPBS": "BritishPoundCoin",
+ "GRFT": "Graft",
+ "GRIM": "GrimCoin",
+ "GRIMM": "Grimm",
+ "GRIN": "Grin",
+ "GRIN29": "Grin",
+ "GRIN31": "Grin",
+ "GRIN32": "Grin",
+ "GRLC": "GarliCoin",
+ "GRS": "Groestl",
+ "GRV": "Gravium",
+ "GSR": "GeyserCoin",
+ "GUN": "GunCoin",
+ "GXG": "GroinCoin",
+ "GXX": "GravityCoin",
+ "HANA": "HanaCoin",
+ "HATCH": "Hatch",
+ "HBC": "HotelbyteCoin",
+ "HCASH": "HCash",
+ "HDAC": "Hunday DAC",
+ "HLC": "Qitmeer",
+ "HLX": "Hilux",
+ "HNS": "Handshake",
+ "HODL": "HodlCoin",
+ "HORA": "Hydnora",
+ "HPC": "Happy",
+ "HTA": "Historia",
+ "HTH": "HthCoin",
+ "HUSH": "Hush",
+ "HYC": "Hycon",
+ "IBH": "iBitHub",
+ "IC": "Ignition",
+ "IDX": "IndexChain",
+ "IFX": "Infinex",
+ "IMG": "ImageCoin",
+ "IMGC": "ImageCash",
+ "INFO": "InfoCoin",
+ "INN": "Innova",
+ "IOTS": "IOTS",
+ "IQ": "IQ Cash",
+ "IRD": "Iridium",
+ "IRL": "IrishCoin",
+ "ISN": "69Coin",
+ "ISO": "IsotopeC",
+ "ITC": "InterCoin",
+ "ITZ": "Interzone",
+ "JEM": "JemCash",
+ "JINY": "JinyCoin",
+ "JOYS": "Joys Digital",
+ "KCN": "KylaCoin",
+ "KDA": "Kadena",
+ "KLR": "Klaro",
+ "KMD": "Komodo",
+ "KOT": "Kotia",
+ "KOTO": "koto",
+ "KRB": "Karbo",
+ "KREDS": "Kreds",
+ "KVA": "KevaCoin",
+ "KYAN": "Kyanite",
+ "KYF": "Cryptofranc",
+ "KZC": "KZCash",
+ "LANA": "Lana",
+ "LBC": "Lbryio",
+ "LBTC": "LitebitCoin",
+ "LCC": "LiteCash",
+ "LCNT": "Lucent",
+ "LCP": "Litecoin Plus",
+ "LDC": "LeedCoin",
+ "LEVO": "LevoCoin",
+ "LINC": "Linc",
+ "LINX": "Linx",
+ "LITB": "LightBit",
+ "LNC": "Blocklancer",
+ "LOG": "WoodCoin",
+ "LOKI": "Loki",
+ "LONG": "LongCoin",
+ "LRA": "Learnium",
+ "LTB": "LiteBar",
+ "LTC": "LiteCoin",
+ "LTCX": "Litecoinx",
+ "LTFN": "Ltfinance",
+ "LTHN": "Lethean",
+ "LTNCG": "LightningCash-Gold",
+ "LTZ": "LitecoinZ",
+ "LUCKY": "Lucky",
+ "LUX": "LuxCoin",
+ "MAC": "Machine",
+ "MARS": "Mars Token",
+ "MAX": "MaxCoin",
+ "MAZA": "MazaCoin",
+ "MBC": "MicrobitCoin",
+ "MBGL": "Mobitglobal",
+ "MDEX": "Moondex",
+ "MEC": "MegaCoin",
+ "MEG": "MegaCoin",
+ "MEK": "Meraki",
+ "MGPC": "MagpieCoin",
+ "MINTME": "MintmeCoin",
+ "MIX": "Mix",
+ "MNC": "MinCoin",
+ "MNX": "Minex",
+ "MOAC": "Moac",
+ "MOG": "Mogwai",
+ "MON": "Btcmonster",
+ "MONA": "Mona",
+ "MOON": "MoonCoin",
+ "MOTA": "MotaCoin",
+ "MRL": "Morelo",
+ "MSR": "Masari",
+ "MUSIC": "MusiCoin",
+ "MWC": "MimbleWimbleCoin",
+ "MWC29": "MimbleWimbleCoin",
+ "MWC31": "MimbleWimbleCoin",
+ "MYNT": "Mynt",
+ "NAD": "Nadir",
+ "NAH": "StrayaCoin",
+ "NBX": "NibbleClassic",
+ "NEET": "NeetCoin",
+ "NEVA": "NevaCoin",
+ "NILU": "Nilu",
+ "NIM": "Nimiq",
+ "NLG": "Gulden",
+ "NMC": "NameCoin",
+ "NMS": "Numus",
+ "NOBL": "NobleCoin",
+ "NOON": "NoonCoin",
+ "NSD": "Nasda",
+ "NTBC": "Note Blockchain",
+ "NUKO": "Nekonium",
+ "NVC": "NovaCoin",
+ "NXS": "Nexus",
+ "NYAN": "NyanCoin",
+ "NYGC": "NewyorkgoldCoin",
+ "NYX": "NyxCoin",
+ "OBTC": "OpticalBitcoin",
+ "OBV": "OblivionCoin",
+ "OCP": "Ocp",
+ "OMEGA": "Omega",
+ "ONION": "Deeponion",
+ "ONX": "Onix",
+ "ORB": "OrbitCoin",
+ "PAC": "Paccoin",
+ "PASC": "PascalCoin",
+ "PBTC": "PhotonicBitcoin",
+ "PCOIN": "PioneerCoin",
+ "PESP": "ThePeopleCoin",
+ "PEXA": "PexaCoin",
+ "PGC": "PegasCoin",
+ "PGN": "Pigeon",
+ "PGO": "PengolinCoin",
+ "PHC": "Profithunter",
+ "PHL": "Placeholders",
+ "PINK": "PinkCoin",
+ "PIRL": "Pirl",
+ "PLE": "Plenteum",
+ "PLSR": "PulsarCoin",
+ "PLUS": "PlusoneCoin",
+ "PLUS1": "PlusoneCoin",
+ "PMEER": "Qitmeer",
+ "POLY": "Polytimos",
+ "PPC": "PeerCoin",
+ "PRIV": "Privcy",
+ "PRKL": "Perkle",
+ "PTC": "PesetaCoin",
+ "PURA": "Pura",
+ "PWR": "PwrCoin",
+ "PXC": "PhoenixCoin",
+ "PYRK": "Pyrk",
+ "QBC": "Quebecoin",
+ "QBS": "Qbase",
+ "QKC": "QuarkChain",
+ "QOGE": "QogeCoin",
+ "QRL": "Quantum",
+ "QRN": "Qureno",
+ "QWC": "QwertyCoin",
+ "RACE": "Race",
+ "RAP": "Rapture",
+ "REA": "RealCoin",
+ "REAN": "ReaCoin",
+ "REDN": "Reden",
+ "REOSC": "REOSC Ecosystem",
+ "RES": "Resistance",
+ "RIC": "RieCoin",
+ "RING": "Ring",
+ "RITO": "RitoCoin",
+ "RNG": "Ring",
+ "ROI": "RoiCoin",
+ "ROL": "Roller",
+ "RPG": "RPG",
+ "RTID": "RtidCoin",
+ "RTM": "Raptor3um",
+ "RVC": "RavencoinClassic",
+ "RVL": "RavencoinLite",
+ "RVN": "RavenCoin",
+ "RVNKP": "Testnet RVN",
+ "RVNt": "Testnet RVN",
+ "RYO": "Ryo",
+ "SAFE": "SafeCoin",
+ "SAFEC": "SafecoinClassic",
+ "SAP": "Methuselah",
+ "SAROS": "Soros",
+ "SATO": "SatoshiCrypto",
+ "SC": "SiaCoin",
+ "SCASH": "SafeCash",
+ "SCC": "Stockchain",
+ "SCIFI": "Scifi",
+ "SCRIBE": "Scribe",
+ "SCRIV": "Scriv",
+ "SECI": "SeciCoin",
+ "SERO": "Superzero",
+ "SFC": "SafeChain",
+ "SFX": "SafexCash",
+ "SHIELD": "Shield",
+ "SHND": "StrongHands",
+ "SIB": "Sib",
+ "SIN": "Sinovative",
+ "SKC": "SkeinCoin",
+ "SMART": "SmartCash",
+ "SMLY": "Smileycoin",
+ "SONO": "Sono",
+ "SOV": "Sovereign",
+ "SPDR": "Spider",
+ "SPK": "Sparkspay",
+ "SPLD": "SplendidCoin",
+ "SPRX": "SprintPay",
+ "SRC": "Secure",
+ "SSC": "SuperstringChain",
+ "STAK": "Straks",
+ "START": "StartCoin",
+ "STM": "StimCoin",
+ "STRMS": "Streamies",
+ "SUGAR": "SugarChain",
+ "SUMO": "Sumokoin",
+ "SUN": "SunCoin",
+ "SUSU": "SusuCoin",
+ "SWAMP": "SwampCoin",
+ "SXC": "SexCoin",
+ "SYS": "SysCoin",
+ "TCR": "TecraCoin",
+ "TDC": "TideCoin",
+ "TENT": "TentCoin",
+ "TEO": "Trusteth Reorigin",
+ "THOR": "ThorCoin",
+ "TIM": "TimCoin",
+ "TIPS": "FedoraCoin",
+ "TIT": "TitCoin",
+ "TLO": "Talleo",
+ "TLR": "Taler",
+ "TLT": "TiltCoin",
+ "TNET": "Title",
+ "TON": "TonCoin",
+ "TOPAZ": "Topaz",
+ "TRAID": "Traid",
+ "TRB": "Tellor",
+ "TRC": "TerraCoin",
+ "TROLL": "TrollCoin",
+ "TRTL": "Turtle",
+ "TSF": "Teslafunds",
+ "TTN": "TitanCoin",
+ "TTNZ": "Tritanium",
+ "TUBE": "Bittube",
+ "TUBE4": "Bittube",
+ "TUX": "TuxCoin",
+ "TZC": "TrezarCoin",
+ "UBQ": "UBIQ",
+ "UFO": "UfoProject",
+ "UIS": "Unitus",
+ "UMBRU": "UMBRU",
+ "UPX": "Uplexa",
+ "URALS": "UralsCoin",
+ "URX": "Uranium-x",
+ "UT": "ULORD",
+ "V8": "V8 Coin",
+ "VBK": "Veriblock",
+ "VDL": "Vidulum",
+ "VDS": "VDimension",
+ "VECO": "Veco",
+ "VEGI": "Veggie",
+ "VEIL": "Veil",
+ "VGC": "5G-CASH",
+ "VIA": "ViaCoin",
+ "VIC": "Victorim",
+ "VIOG": "Viog",
+ "Viridi": "Viridi",
+ "VIVO": "Vivo",
+ "VLS": "Veles",
+ "VOLLAR": "VDimension",
+ "VOT": "VoteCoin",
+ "VRG": "Verge",
+ "VRM": "VeriumReserve",
+ "VRSC": "Verus",
+ "VTC": "VertCoin",
+ "WATC": "WhatCoin",
+ "WDC": "WorldCoin",
+ "WDF": "WildfireCoin",
+ "WHL": "WhaleCoin",
+ "WLI": "Wanliuno",
+ "WOW": "Wownero",
+ "WRKZ": "WrkzCoin",
+ "WSBC": "WallstreetBets",
+ "WXC": "WxCoin",
+ "XBG": "BitGrin",
+ "XBG29": "BitGrin",
+ "XBG31": "BitGrin",
+ "XBTG": "Bitgem",
+ "XBTX": "Bitcoin Subsidium",
+ "XCASH": "XCash",
+ "XCH": "Chia",
+ "XCN": "Cryptonite",
+ "XCY": "CyprusCoin",
+ "XDN": "Digitalnote",
+ "XDNA": "XDNA",
+ "XEBEC": "Xebec",
+ "XEC": "eCash",
+ "XEQ": "Equilibria",
+ "XFR": "Firo",
+ "XGCS": "XgalaxyCoin",
+ "XGM": "Defis",
+ "XHV": "Haven",
+ "XJO": "JouleCoin",
+ "XLA": "Scala",
+ "XMC": "MoneroClassic",
+ "XMCC": "Monoeci",
+ "XMG": "Magi",
+ "XMN": "Motionproject",
+ "XMR": "Monero",
+ "XMV": "MoneroV",
+ "XMY": "Myriad",
+ "XOL": "Xolentum",
+ "XRC": "Bitcoin Rhodium",
+ "XRD": "Raven Dark",
+ "XSC": "XSC",
+ "XSG": "Snowgem",
+ "XSH": "Shield",
+ "XSHB": "Shield",
+ "XSPC": "Spectre",
+ "XSR": "SucreCoin",
+ "XTA": "Italo",
+ "XTNC": "XtendCash",
+ "XVG": "VERGE",
+ "XVP": "VirtaCoinPlus",
+ "XWP": "Swap",
+ "XZC": "Firo",
+ "XZX": "Zixx",
+ "YDA": "YadaCoin",
+ "YEC": "YCash",
+ "YOC": "YoCoin",
+ "YTN": "Yenten",
+ "ZANO": "Zano",
+ "ZCH": "0Cash",
+ "ZCL": "Zclassic",
+ "ZCR": "Zcore",
+ "ZEC": "ZCash",
+ "ZEL": "ZelCash",
+ "ZELS": "Zelantus",
+ "ZEN": "ZenCash",
+ "ZENX": "ZentoshiCoin",
+ "ZEON": "Zeon",
+ "ZER": "Zero",
+ "ZERC": "ZeroClassic",
+ "ZMY": "Zumy",
+ "ZNY": "Bitzeny",
+ "ZOC": "01Coin",
+ "ZP": "ZenProtocol",
+ "ZUR": "ZurCoin",
+ "ZYON": "BitZyon"
+}
diff --git a/Data/DagData.json b/Data/DagData.json
new file mode 100644
index 0000000000..8c0d58620b
--- /dev/null
+++ b/Data/DagData.json
@@ -0,0 +1,138 @@
+{
+ "Currency": {
+ "ETH": {
+ "BlockHeight": 14685823,
+ "CoinName": "Ethereum",
+ "DAGsize": 5175769472,
+ "Epoch": 489
+ },
+ "EGEM": {
+ "BlockHeight": 10358974,
+ "CoinName": "EtherGem",
+ "DAGsize": 3967809152,
+ "Epoch": 345
+ },
+ "CLO": {
+ "BlockHeight": 9802050,
+ "CoinName": "Callisto",
+ "DAGsize": 3808427648,
+ "Epoch": 326
+ },
+ "QKC": {
+ "BlockHeight": 9650732,
+ "CoinName": "QuarkChain",
+ "DAGsize": 3766481536,
+ "Epoch": 321
+ },
+ "MOAC": {
+ "BlockHeight": 9079633,
+ "CoinName": "Moac",
+ "DAGsize": 3607098752,
+ "Epoch": 302
+ },
+ "ETHO": {
+ "BlockHeight": 8709768,
+ "CoinName": "Ether1",
+ "DAGsize": 3506434432,
+ "Epoch": 290
+ },
+ "ETC": {
+ "BlockHeight": 15033595,
+ "CoinName": "Ethereum Classic",
+ "DAGsize": 3170893184,
+ "Epoch": 250
+ },
+ "NUKO": {
+ "BlockHeight": 7217546,
+ "CoinName": "Nekonium",
+ "DAGsize": 3087003776,
+ "Epoch": 240
+ },
+ "REOSC": {
+ "BlockHeight": 7114083,
+ "CoinName": "REOSC Ecosystem",
+ "DAGsize": 3061837696,
+ "Epoch": 237
+ },
+ "AKA": {
+ "BlockHeight": 6945366,
+ "CoinName": "Akroma",
+ "DAGsize": 3011508352,
+ "Epoch": 231
+ },
+ "ETP": {
+ "BlockHeight": 6571697,
+ "CoinName": "Metaverse",
+ "DAGsize": 2910843008,
+ "Epoch": 219
+ },
+ "ESN": {
+ "BlockHeight": 6345988,
+ "CoinName": "EtherSocial",
+ "DAGsize": 2843734144,
+ "Epoch": 211
+ },
+ "NILU": {
+ "BlockHeight": 6165034,
+ "CoinName": "Nilu",
+ "DAGsize": 2793401984,
+ "Epoch": 205
+ },
+ "EXP": {
+ "BlockHeight": 5890509,
+ "CoinName": "Expanse",
+ "DAGsize": 2717907328,
+ "Epoch": 196
+ },
+ "ATH": {
+ "BlockHeight": 5530536,
+ "CoinName": "Atheios",
+ "DAGsize": 2617240448,
+ "Epoch": 184
+ },
+ "ERG": {
+ "BlockHeight": 739444,
+ "CoinName": "Ergo",
+ "DAGsize": 1275067264,
+ "Epoch": 24
+ },
+ "PGC": {
+ "BlockHeight": 4579660,
+ "CoinName": "PegasCoin",
+ "DAGsize": 2348808064,
+ "Epoch": 152
+ },
+ "UBQ": {
+ "BlockHeight": 2227832,
+ "CoinName": "UBIQ",
+ "DAGsize": 1694497664,
+ "Epoch": 74
+ },
+ "DBIX": {
+ "BlockHeight": 1721407,
+ "CoinName": "DubaiCoin",
+ "DAGsize": 1551892096,
+ "Epoch": 57
+ },
+ "ERE": {
+ "BlockHeight": 484111,
+ "CoinName": "Ethercore",
+ "DAGsize": 1207958912,
+ "Epoch": 16
+ },
+ "RVN": {
+ "BlockHeight": 2255807,
+ "CoinName": "RavenCoin",
+ "DAGsize": 3590324096,
+ "Epoch": 300
+ },
+ "*": {
+ "BlockHeight": 15033595,
+ "CoinName": "*",
+ "DAGsize": 5175769472,
+ "Epoch": 489
+ }
+ },
+ "Updated_Minerstat": "2022-04-30T13:27:07.1787145Z",
+ "Updated_Ravencoin": "2022-04-30T13:27:08.2546657Z"
+}
diff --git a/Data/Devices.json b/Data/Devices.json
new file mode 100644
index 0000000000..a35c54783f
--- /dev/null
+++ b/Data/Devices.json
@@ -0,0 +1,69 @@
+{
+ "amd": {
+ "Type": "GPU",
+ "Vendor": "AMD",
+ "Id": "*",
+ "Type_Id": "*",
+ "Vendor_Id": "*",
+ "Type_Vendor_Id": "{1}"
+ },
+ "cpu": {
+ "Type": "CPU",
+ "Vendor": "*",
+ "Id": "*",
+ "Type_Id": "{1}",
+ "Vendor_Id": "*",
+ "Type_Vendor_Id": "*"
+ },
+ "device": {
+ "Type": "*",
+ "Vendor": "*",
+ "Id": "{1}",
+ "Type_Id": "*",
+ "Vendor_Id": "*",
+ "Type_Vendor_Id": "*"
+ },
+ "gpu": {
+ "Type": "GPU",
+ "Vendor": "*",
+ "Id": "*",
+ "Type_Id": "{1}",
+ "Vendor_Id": "*",
+ "Type_Vendor_Id": "*"
+ },
+ "intel": {
+ "Type": "GPU",
+ "Vendor": "INTEL",
+ "Id": "*",
+ "Type_Id": "*",
+ "Vendor_Id": "*",
+ "Type_Vendor_Id": "{1}"
+ },
+ "nvidia": {
+ "Type": "GPU",
+ "Vendor": "NVIDIA",
+ "Id": "*",
+ "Type_Id": "*",
+ "Vendor_Id": "*",
+ "Type_Vendor_Id": "{1}"
+ },
+ "opencl": {
+ "Type": "GPU",
+ "Vendor": "*",
+ "Index": "*",
+ "Type_Index": "*",
+ "Vendor_Index": "*",
+ "Type_Vendor_Index": "*",
+ "PlatformId": "{1}",
+ "PlatformId_Index": "*",
+ "Type_PlatformId_Index": "{2}"
+ },
+ "slot": {
+ "Type": "GPU",
+ "Vendor": "*",
+ "Slot": "*",
+ "Type_Slot": "{1}",
+ "Vendor_Slot": "*",
+ "Type_Vendor_Slot": "*"
+ }
+}
\ No newline at end of file
diff --git a/Data/DonationData.json b/Data/DonationData.json
new file mode 100644
index 0000000000..d7d3976c6f
--- /dev/null
+++ b/Data/DonationData.json
@@ -0,0 +1,26 @@
+[
+ {
+ "Name": "MrPlus",
+ "Wallets": {
+ "BTC": "134bw4oTorEJUUVFhokDQDfNqTs7rBMNYy"
+ },
+ "MiningPoolHubUserName": "MrPlus"
+ },
+ {
+ "Name": "Nemo",
+ "Wallets": {
+ "BTC": "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE"
+ },
+ "MiningPoolHubUserName": "nemo"
+ },
+ {
+ "Name": "uselessguru",
+ "Wallets": {
+ "BTC": "1GPSq8txFnyrYdXL8t6S94mYdF8cGqVQJF",
+ "ETC": "0x7CF99ec9029A98AFd385f106A93977D8105Fec0f",
+ "ETH": "0x92e6F22C1493289e6AD2768E1F502Fc5b414a287"
+ },
+ "MiningPoolHubUserName": "uselessguru",
+ "ProHashingUserName": "uselessguru"
+ }
+]
diff --git a/NM.ico b/Data/NM.ico
similarity index 100%
rename from NM.ico
rename to Data/NM.ico
diff --git a/Data/NM.png b/Data/NM.png
new file mode 100644
index 0000000000..07946f019c
Binary files /dev/null and b/Data/NM.png differ
diff --git a/Data/PoolData.json b/Data/PoolData.json
new file mode 100644
index 0000000000..5fcb4f7b86
--- /dev/null
+++ b/Data/PoolData.json
@@ -0,0 +1,325 @@
+{
+ "BlockMasters": {
+ "BalancesKeepAlive": 120, // Old accounts are purged every 120 Days
+ "GuaranteedPayoutCurrencies": [
+ "BTC",
+ "DOGE",
+ "LTC"
+ ],
+ "PayoutThreshold": {
+ "mBTC": 1.65,
+ "LTC": 0.05,
+ "DODGE": 20,
+ "*": "0.01 mBTC" // From pool: All other coins is paid once you reach the coin equivalent to 0.0001 BTC every 4 hours or 0.00001 BTC on Sundays
+ },
+ "PayoutCurrency": "[Default]",
+ "Region": [
+ "as",
+ "eu",
+ "us"
+ ],
+ "Variant": {
+ "BlockMasters": {
+ "DivisorMultiplier": 1000000,
+ "PriceField": "estimate_current"
+ },
+ "BlockMasters24hr": {
+ "DivisorMultiplier": 1000000,
+ "PriceField": "estimate_last24h"
+ },
+ "BlockMastersPlus": {
+ "DivisorMultiplier": 1000000,
+ "PriceField": "Plus_Price"
+ }
+ }
+ },
+ "HiveON": {
+ "BalancesKeepAlive": 90, // No expiration communicated by pool, use 90 days just to be sure
+ "GuaranteedPayoutCurrencies": [
+ "ETC",
+ "ETH"
+ ],
+ "PayoutCurrencies": [
+ "ETC",
+ "ETH"
+ ],
+ "PayoutThreshold": {
+ "ETC": 1,
+ "ETH": 0.1
+ },
+ "Region": [
+ "ru",
+ "eu",
+ "na",
+ "naw",
+ "aspac",
+ "usw",
+ "use"
+ ],
+ "Variant": {
+ "HiveON": {
+ }
+ }
+ },
+ "MiningPoolHub": {
+ "BalancesKeepAlive": 90, // No expiration communicated by pool
+ "Fee": 0.009,
+ "GuaranteedPayoutCurrencies": [
+ "ADZ",
+ "AUR",
+ "BSTY",
+ "BCH",
+ "BTC",
+ "BTG",
+ "DASH",
+ "DGB",
+ "ESN",
+ "ETC",
+ "ETH",
+ "ETN",
+ "EXP",
+ "FTC",
+ "GAME",
+ "GRS",
+ "LTC",
+ "MAX",
+ "MONA",
+ "MUSIC",
+ "RVN",
+ "SC",
+ "START",
+ "SXC",
+ "VTC",
+ "XZC",
+ "XMR",
+ "XMY",
+ "XVG",
+ "ZCL",
+ "ZEC",
+ "ZEN"
+ ],
+ "Region": [
+ "Asia",
+ "EU",
+ "US"
+ ],
+ "Variant": {
+ "MiningPoolHub": {
+ },
+ "MiningPoolHubCoins": {
+ }
+ }
+ },
+ "NiceHash": {
+ "BalancesKeepAlive": 180, // Your NiceHash Account may be deactivated due to your inactivity
+ "EarningsAdjustmentFactor": 1.0, // NiceHash earnings estimates are always correct
+ "GuaranteedPayoutCurrencies": [
+ "BTC" // Required here for donation
+ ],
+ "Region": [
+ "N/A (Anycast)",
+ "eu-west",
+ "eu-north",
+ "usa-west",
+ "usa-east"
+ ],
+ "Variant": {
+ "NiceHash External": {
+ "Fee": 0.05,
+ "PayoutCurrency": "BTC", // Only BTC is supported
+ "PayoutThreshold": {
+ "mBTC": 1
+ }
+ },
+ "NiceHash Internal": {
+ "Fee": 0.02,
+ "PayoutCurrency": "BTC", // Only BTC is supported
+ "PayoutThreshold": {
+ "mBTC": 0.5
+ }
+ }
+ }
+ },
+ "NLPool": {
+ "BalancesKeepAlive": 30, // Accounts with no mining activity for 1 month are purged
+ "GuaranteedPayoutCurrencies": [
+ "BTC",
+ "LTC"
+ ],
+ "PayoutCurrency": "[Default]",
+ "PayoutThreshold": {
+ "LTC": 0.05,
+ "mBTC": 1
+ },
+ "Region": [
+ "eu-west"
+ ],
+ "Variant": {
+ "NLPool": {
+ "DivisorMultiplier": 1000000,
+ "PriceField": "estimate_current"
+ },
+ "NLPool24hr": {
+ "DivisorMultiplier": 1000000,
+ "PriceField": "estimate_last24h"
+ },
+ "NLPoolPlus": {
+ "DivisorMultiplier": 1000000,
+ "PriceField": "Plus_Price"
+ }
+ }
+ },
+ "ProHashing": {
+ "BalancesKeepAlive": 90, // The customer has not mined with the pool for 90 days (https://prohashing.com/help/prohashing-legal-information#terms)
+ "GuaranteedPayoutCurrencies": [
+ "BTC",
+ "LTC"
+ ],
+ "PayoutThreshold": {
+ "mBTC": 0,
+ "LTC": 0.010950859265481713,
+ "USD": 10
+ },
+ "Region": [
+ "EU",
+ "US"
+ ],
+ "Variant": {
+ "ProHashing": {
+ "DivisorMultiplier": 1,
+ "PriceField": "estimate_current"
+ },
+ "ProHashing24hr": {
+ "DivisorMultiplier": 0.001,
+ "PriceField": "estimate_last24h"
+ },
+ "ProHashingPlus": {
+ "DivisorMultiplier": 1,
+ "PriceField": "Plus_Price"
+ }
+ }
+ },
+ "TonPool": {
+ "GuaranteedPayoutCurrencies": [
+ "TON"
+ ],
+ "PayoutCurrency": "TON",
+ "Region": [
+ "asia",
+ "eu",
+ "hk",
+ "na"
+ ],
+ "Variant": {
+ "TonPool": {
+ "DivisorMultiplier": 1000000000000000000,
+ "PriceField": "last_24h"
+ }
+ }
+ },
+ "TonWhales": {
+ "GuaranteedPayoutCurrencies": [
+ "TON"
+ ],
+ "PayoutCurrency": "TON",
+ "Region": [
+ "ru"
+ ],
+ "Variant": {
+ "TonWhales": {
+ "DivisorMultiplier": 1000000000000000000,
+ "PriceField": "profitabilityPerGh"
+ }
+ }
+ },
+ "ZergPool": {
+ "BalancesKeepAlive": 90, // Accounts with no mining activity for 3 months are purged
+ "GuaranteedPayoutCurrencies": [
+ "BCH",
+ "BNB",
+ "BTC",
+ "CAKE",
+ "DASH",
+ "DOGE",
+ "ETH",
+ "KLV",
+ "LTC",
+ "MATIC",
+ "RVN",
+ "SHIB",
+ "TRX",
+ "USDT",
+ "USDT-BEP20",
+ "USDT-TRC20",
+ "WIN"
+ ],
+ "PayoutCurrency": "[Default]",
+ "PayoutThreshold": { // PayoutThreshold is retrieved from API data, but can be set here to override value set by pool (can only set higher)
+ // e.g. "mBTC": 5
+ },
+ "Region": [
+ "N/A (Anycast)",
+ "asia",
+ "eu",
+ "na"
+ ],
+ "Variant": {
+ "ZergPool": {
+ "DivisorMultiplier": 1000000,
+ "PriceField": "estimate_current"
+ },
+ "ZergPool24hr": {
+ "DivisorMultiplier": 1000000,
+ "PriceField": "estimate_current24h"
+ },
+ "ZergPoolCoins": {
+ "DivisorMultiplier": 1000000,
+ "PriceField": "estimate_current"
+ },
+ "ZergPoolCoinsPlus": {
+ "DivisorMultiplier": 1000000,
+ "PriceField": "Plus_Price"
+ },
+ "ZergPoolPlus": {
+ "DivisorMultiplier": 1000000,
+ "PriceField": "Plus_Price"
+ }
+ }
+ },
+ "ZPool": {
+ "BalancesKeepAlive": 90, // Inactive accounts are purged after 90 days
+ "GuaranteedPayoutCurrencies": [
+ "BTC",
+ "DASH",
+ "DGB",
+ "KMD",
+ "LTC",
+ "RVN"
+ ],
+ "PayoutCurrency": "[Default]",
+ "PayoutThreshold": {
+ "mBTC": 1.5,
+ "*": 0.0125
+ },
+ "Region": [
+ "eu",
+ "jp",
+ "na",
+ "sea"
+ ],
+ "Variant": {
+ "ZPool": {
+ "DivisorMultiplier": 1000000,
+ "PriceField": "estimate_current"
+ },
+ "ZPool24hr": {
+ "DivisorMultiplier": 1000000000,
+ "PriceField": "estimate_current24h"
+ },
+ "ZPoolPlus": {
+ "DivisorMultiplier": 1000000,
+ "PriceField": "Plus_Price"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Data/PoolsConfig-Recommended.json b/Data/PoolsConfig-Recommended.json
new file mode 100644
index 0000000000..7ac5e18699
--- /dev/null
+++ b/Data/PoolsConfig-Recommended.json
@@ -0,0 +1,65 @@
+{
+ "Blockmasters" : {
+ "Algorithm" : [
+ "+m7m"
+ ],
+ "Variant": {
+ "BlockmastersPlus": {
+ }
+ }
+ },
+ "MiningPoolHub": {
+ "Algorithm" :[
+ "+Ethash",
+ "+KawPoW"
+ ],
+ "Variant": {
+ "MiningPoolHubCoins": {
+ }
+ }
+ },
+ "NiceHash": {
+ "Algorithm": [
+ "+Cuckaroom",
+ "+Cuckaroo29bfc",
+ "+Cuckarooz29",
+ "+Cuckoocycle",
+ "+Cuckaroo29",
+ "+Cuckarood29",
+ "+Cuckatoo31",
+ "+Cuckatoo32",
+ "+Eaglesong",
+ "+Ethash",
+ "+Handshake"
+ ],
+ "Variant": {
+ "NiceHash External": {
+ }
+ }
+ },
+ "ZergPool": {
+ "Algorithm": [
+ "+CryptonightConceal",
+ "+CryptonightHaven",
+ "+CryptonightHeavy",
+ "+CryptonightHeavyx",
+ "+CryptonightUpx",
+ "+Ethash",
+ "+Randomsfx",
+ "+Randomwow",
+ "+VerusHash",
+ "+YescryptR8g",
+ "+Yespoweriots"
+ ],
+ "Variant": {
+ "ZergPoolCoinsPlus": {
+ }
+ }
+ },
+ "ZPool": {
+ "Variant": {
+ "ZPoolPlus": {
+ }
+ }
+ }
+}
diff --git a/Data/Regions.json b/Data/Regions.json
new file mode 100644
index 0000000000..916e2ead01
--- /dev/null
+++ b/Data/Regions.json
@@ -0,0 +1,27 @@
+{
+ "as": ["Asia", "HongKong", "Japan", "Russia", "Europe North", "Europe West", "USA East", "USA West"],
+ "Asia": ["Asia", "HongKong", "Japan", "Russia", "Europe North", "Europe West", "USA East", "USA West"],
+ "aspac": ["Asia", "HongKong", "Japan", "Russia", "Europe North", "Europe West", "USA East", "USA West"],
+ "eu": ["Europe West", "Europe North", "Russia", "USA West", "USA East", "HongKong", "Asia", "Japan"],
+ "Europe North": ["Europe North", "Europe West", "Russia", "USA West", "USA East", "HongKong", "Asia", "Japan"],
+ "Europe West": ["Europe West", "Europe North", "Russia", "USA West", "USA East", "HongKong", "Asia", "Japan"],
+ "eu-north": ["Europe North", "Europe West", "Russia", "USA West", "USA East", "HongKong", "Asia", "Japan"],
+ "eu-west": ["Europe West", "Europe North", "Russia", "USA West", "USA East", "HongKong", "Asia", "Japan"],
+ "hk": ["HongKong", "Asia", "Japan", "Russia", "Europe North", "Europe West", "USA East", "USA West"],
+ "HongKong": ["HongKong", "Asia", "Japan", "Russia", "Europe North", "Europe West", "USA East", "USA West"],
+ "Japan": ["Japan", "HongKong", "Asia", "Russia", "Europe North", "Europe West", "USA East", "USA West"],
+ "jp": ["Japan", "HongKong", "Asia", "Russia", "Europe North", "Europe West", "USA East", "USA West"],
+ "na": ["USA West", "USA East", "Europe West", "Europe North", "Russia", "HongKong", "Asia", "Japan"],
+ "Russia": ["Russia", "Europe North", "Europe West", "HongKong", "Asia", "Japan", "USA East", "USA West"],
+ "ru": ["Russia", "Europe North", "Europe West", "HongKong", "Asia", "Japan", "USA West", "USA East"],
+ "sea": ["Asia", "HongKong", "Japan", "Russia", "Europe North", "Europe West", "USA East", "USA West"],
+ "us": ["USA West", "USA East", "Europe West", "Europe North", "Russia", "HongKong", "Japan", "Asia"],
+ "naw": ["USA West", "USA East", "Europe West", "Europe North", "Russia", "HongKong", "Asia", "Japan"],
+ "usa": ["USA West", "USA East", "Europe West", "Europe North", "Russia", "HongKong", "Japan", "Asia"],
+ "use": ["USA East", "USA West", "Japan", "HongKong", "Asia", "Europe North", "Russia", "Europe West"],
+ "usw": ["USA West", "USA East", "Europe West", "Europe North", "Russia", "HongKong", "Asia", "Japan"],
+ "USA East": ["USA East", "USA West", "Japan", "HongKong", "Asia", "Europe North", "Russia", "Europe West"],
+ "USA West": ["USA West", "USA East", "Europe West", "Europe North", "Russia", "HongKong", "Asia", "Japan"],
+ "usa-east": ["USA East", "USA West", "Japan", "HongKong", "Asia", "Europe North", "Russia", "Europe West"],
+ "usa-west": ["USA West", "USA East", "Europe West", "Europe North", "Russia", "HongKong", "Asia", "Japan"]
+}
diff --git a/Data/UnprofitableAlgorithms.json b/Data/UnprofitableAlgorithms.json
new file mode 100644
index 0000000000..d451842729
--- /dev/null
+++ b/Data/UnprofitableAlgorithms.json
@@ -0,0 +1,68 @@
+// Syntax:
+// "AlgorithmName": "*" = Algorithm is unprofitable as primary AND secondary algorithm
+// "AlgorithmName": "1" = Algorithm is unprofitable as primary algorithm, but profitable as secondary algorithm
+// "AlgorithmName": "2" = Algorithm is unprofitable as secondary algorithm, but profitable as primary algorithm
+
+{
+ "Allium": "*",
+ "AstralHash": "*",
+ "Bitcoin": "*",
+ "Bitcore": "*",
+ "Blake2b": "*",
+ "Blake2s": "1",
+ "BlakeCoin": "*",
+ "BlakeVanilla": "*",
+ "Bmw512": "*",
+ "CryptonightR": "*",
+ "C11": "*",
+ "Decred": "1",
+ "Dedal": "*",
+ "Eaglesong": "1",
+ "Equihash965": "*",
+ "Groestl": "*",
+ "Handshake": "1",
+ "Hodl": "*",
+ "HoneyComb": "*",
+ "JeongHash": "*",
+ "Keccak": "1",
+ "KeccakC": "*",
+ "Lbry": "1",
+ "Lyra2RE": "*",
+ "Lyra2RE2": "*",
+ "Lyra2RE3": "*",
+ "Lyra2z": "*",
+ "MegaBtx": "*",
+ "MyriadGroestl": "*",
+ "Nist5": "1",
+ "PadiHash": "*",
+ "PawelHash": "*",
+ "Pascal": "1",
+ "Phi": "*",
+ "Quark": "*",
+ "Qubit": "*",
+ "Randomx": "*",
+ "RandomxArq": "*",
+ "Scrypt": "*",
+ "ScryptN": "*",
+ "Sha256": "*",
+ "Sha256AsicBoost": "*",
+ "SHA256d": "*",
+ "SHA256t": "*",
+ "Sia": "1",
+ "Sib": "*",
+ "Skein": "*",
+ "SkunkHash": "*",
+ "Tensority": "1",
+ "Tribus": "*",
+ "VerusHash": "*",
+ "X11": "*",
+ "X13": "*",
+ "X14": "*",
+ "X15": "*",
+ "X16r": "*",
+ "X16rt": "*",
+ "X16s": "*",
+ "X17": "*",
+ "X22i": "*",
+ "Yesscrypt": "*"
+}
diff --git a/EarningsTrackerJob.ps1 b/EarningsTrackerJob.ps1
deleted file mode 100644
index 7e6f9cd4cc..0000000000
--- a/EarningsTrackerJob.ps1
+++ /dev/null
@@ -1,179 +0,0 @@
-<#
-EarningsTrackerJob written by MrPlus
-Copyright (c) 2018 MrPlus
-NemosMiner is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-NemosMiner is distributed in the hope that it will be useful, See the
-GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-#>
-
-<#
-Product: NemosMiner
-File: EarningsTrackerJob.ps1
-version: 3.8.0.0
-version date: 16 May 2019
-#>
-
-# param(
-# [Parameter(Mandatory=$false)]
-# [String]$Pool = "zpool",
-# [Parameter(Mandatory=$false)]
-# [String]$Wallet = "",
-# [Parameter(Mandatory=$false)]
-# [String]$APIUri,
-# [Parameter(Mandatory=$false)]
-# [Float]$PaymentThreshold = 0.0025,
-# [Parameter(Mandatory=$false)]
-# [Int]$Interval = 10,
-# [Parameter(Mandatory=$false)]
-# [Bool]$EnableLog = $false,
-# [Parameter(Mandatory=$false)]
-# [Bool]$ShowText = $true,
-# [Parameter(Mandatory=$false)]
-# [Bool]$ShowRawData = $true,
-# [Parameter(Mandatory=$false)]
-# [String]$WorkingDirectory = $true
-# )
-# To start the job one could use the following
-# $job = Start-Job -FilePath .\EarningTrackerJob.ps1 -ArgumentList $params
-
-# Remove progress info from job.childjobs.Progress to avoid memory leak
-$ProgressPreference = "SilentlyContinue"
-
-# Fix TLS version erroring
-[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"
-
-# Set Process Priority
-(Get-Process -Id $PID).PriorityClass = "BelowNormal"
-
-$args[0].GetEnumerator() | ForEach-Object { New-Variable -Name $_.Key -Value $_.Value }
-If ($WorkingDirectory) {Set-Location $WorkingDirectory}
-
-sleep $StartDelay
-
-if (-not $APIUri) {
- try {
- $poolapi = Invoke-WebRequest "https://nemosminer.com/data/poolapiref.json" -TimeoutSec 15 -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
- }
- catch {$poolapi = Get-content ".\Config\poolapiref.json" | Convertfrom-json}
- if ($poolapi -ne $null) {
- $poolapi | ConvertTo-json | Out-File ".\Config\poolapiref.json"
- If (($poolapi | ? {$_.Name -eq $pool}).EarnTrackSupport -eq "yes") {
- $APIUri = ($poolapi | ? {$_.Name -eq $pool}).WalletUri
- $PaymentThreshold = ($poolapi | ? {$_.Name -eq $pool}).PaymentThreshold
- $BalanceJson = ($poolapi | ? {$_.Name -eq $pool}).Balance
- $TotalJson = ($poolapi | ? {$_.Name -eq $pool}).Total
- }
- else {return}
- }
-}
-
-$BalanceObjectS = @()
-$TrustLevel = 0
-
-while ($true) {
- $CurDate = Get-Date
- If ($Pool -eq "nicehash") {
- try {
- $TempBalanceData = Invoke-WebRequest ($APIUri + $Wallet) -TimeoutSec 15 -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
- }
- catch { }
- if (-not $TempBalanceData.$BalanceJson) {$TempBalanceData | Add-Member -NotePropertyName $BalanceJson -NotePropertyValue ([decimal]($TempBalanceData.result.Stats | measure -sum $BalanceJson).sum) -Force}
- if (-not $TempBalanceData.$TotalJson) {$TempBalanceData | Add-Member -NotePropertyName $TotalJson -NotePropertyValue ([decimal]($TempBalanceData.result.Stats | measure -sum $BalanceJson).sum) -Force}
- }
- elseif ($Pool -eq "miningpoolhub") {
- try {
- $TempBalanceData = ((((Invoke-WebRequest ($APIUri + $Wallet) -TimeoutSec 15 -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"}).content | ConvertFrom-Json).getuserallbalances).data | Where {$_.coin -eq "bitcoin"})
- }
- catch { }#.confirmed
- }
- else {
- try {
- $TempBalanceData = Invoke-WebRequest ($APIUri + $Wallet) -TimeoutSec 15 -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
- }
- catch { }
- }
- If ($TempBalanceData.$BalanceJson) {$BalanceData = $TempBalanceData}
-
- $BalanceObjectS += [PSCustomObject]@{
- Date = $CurDate
- balance = $BalanceData.$BalanceJson
- unsold = $BalanceData.unsold
- total_unpaid = $BalanceData.total_unpaid
- total_paid = $BalanceData.total_paid
- total_earned = $BalanceData.$TotalJson
- currency = $BalanceData.currency
- }
- $BalanceObject = $BalanceObjectS[$BalanceOjectS.Count - 1]
- If ((($CurDate - ($BalanceObjectS[0].Date)).TotalMinutes) -eq 0) {$CurDate = $CurDate.AddMinutes(1)}
-
-
-
- If ((($CurDate - ($BalanceObjectS[0].Date)).TotalDays) -ge 1) {
- $Growth1 = $BalanceObject.total_earned - (($BalanceObjectS | ? {$_.Date -ge $CurDate.AddHours(-1)}).total_earned | measure -Minimum).Minimum
- $Growth6 = $BalanceObject.total_earned - (($BalanceObjectS | ? {$_.Date -ge $CurDate.AddHours(-6)}).total_earned | measure -Minimum).Minimum
- $Growth24 = $BalanceObject.total_earned - (($BalanceObjectS | ? {$_.Date -ge $CurDate.AddDays(-1)}).total_earned | measure -Minimum).Minimum
- }
- If ((($CurDate - ($BalanceObjectS[0].Date)).TotalDays) -lt 1) {
- $Growth1 = $BalanceObject.total_earned - (($BalanceObjectS | ? {$_.Date -ge $CurDate.AddHours(-1)}).total_earned | measure -Minimum).Minimum
- $Growth6 = $BalanceObject.total_earned - (($BalanceObjectS | ? {$_.Date -ge $CurDate.AddHours(-6)}).total_earned | measure -Minimum).Minimum
- $Growth24 = (($BalanceObject.total_earned - $BalanceObjectS[0].total_earned) / ($CurDate - ($BalanceObjectS[0].Date)).TotalHours) * 24
- }
- If ((($CurDate - ($BalanceObjectS[0].Date)).TotalHours) -lt 6) {
- $Growth1 = $BalanceObject.total_earned - (($BalanceObjectS | ? {$_.Date -ge $CurDate.AddHours(-1)}).total_earned | measure -Minimum).Minimum
- $Growth6 = (($BalanceObject.total_earned - $BalanceObjectS[0].total_earned) / ($CurDate - ($BalanceObjectS[0].Date)).TotalHours) * 6
- }
- If ((($CurDate - ($BalanceObjectS[0].Date)).TotalHours) -lt 1) {
- $Growth1 = (($BalanceObject.total_earned - $BalanceObjectS[0].total_earned) / ($CurDate - ($BalanceObjectS[0].Date)).TotalMinutes) * 60
- }
-
- $AvgBTCHour = If ((($CurDate - ($BalanceObjectS[0].Date)).TotalHours) -ge 1) {(($BalanceObject.total_earned - $BalanceObjectS[0].total_earned) / ($CurDate - ($BalanceObjectS[0].Date)).TotalHours)} else {$Growth1}
- $EarningsObject = [PSCustomObject]@{
- Pool = $pool
- Wallet = $Wallet
- Date = $CurDate
- StartTime = $BalanceObjectS[0].Date
- balance = $BalanceObject.balance
- unsold = $BalanceObject.unsold
- total_unpaid = $BalanceObject.total_unpaid
- total_paid = $BalanceObject.total_paid
- total_earned = $BalanceObject.total_earned
- currency = $BalanceObject.currency
- GrowthSinceStart = $BalanceObject.total_earned - $BalanceObjectS[0].total_earned
- Growth1 = $Growth1
- Growth6 = $Growth6
- Growth24 = $Growth24
- AvgHourlyGrowth = $AvgBTCHour
- BTCD = $AvgBTCHour * 24
- EstimatedEndDayGrowth = If ((($CurDate - ($BalanceObjectS[0].Date)).TotalHours) -ge 1) {($AvgBTCHour * ((Get-Date -Hour 0 -Minute 00 -Second 00).AddDays(1).AddSeconds(-1) - $CurDate).Hours)} else {$Growth1 * ((Get-Date -Hour 0 -Minute 00 -Second 00).AddDays(1).AddSeconds(-1) - $CurDate).Hours}
- EstimatedPayDate = if ($PaymentThreshold) {IF ($BalanceObject.balance -lt $PaymentThreshold) {If ($AvgBTCHour -gt 0) {$CurDate.AddHours(($PaymentThreshold - $BalanceObject.balance) / $AvgBTCHour)} Else {"Unknown"}} else {"Next Payout !"}}else {"Unknown"}
- TrustLevel = if (($CurDate - ($BalanceObjectS[0].Date)).TotalMinutes -le 360) {($CurDate - ($BalanceObjectS[0].Date)).TotalMinutes / 360}else {1}
- PaymentThreshold = $PaymentThreshold
- TotalHours = ($CurDate - ($BalanceObjectS[0].Date)).TotalHours
- }
-
- $EarningsObject
- if ($EnableLog) {$EarningsObject | Export-Csv -NoTypeInformation -Append ".\Logs\EarningTracker-$($Pool).csv"}
-
-
- If ($BalanceObjectS.Count -gt 1) {$BalanceObjectS = $BalanceObjectS | ? {$_.Date -ge $CurDate.AddDays(-1).AddHours(-1)}}
-
- # Some pools do reset "Total" after payment (zpool)
- # Results in showing bad negative earnings
- # Detecting if current is more than 50% less than previous and reset history if so
- If ($BalanceObject.total_earned -lt ($BalanceObjectS[$BalanceObjectS.Count - 2].total_earned / 2)) {$BalanceObjectS = @(); $BalanceObjectS += $BalanceObject}
-
-
- # Sleep until next update based on $Interval. Modulo $Interval.
- # Sleep (60*($Interval-((get-date).minute%$Interval))) # Changed to avoid pool API load.
- If (($EarningsObject.Date - $EarningsObject.StartTime).TotalMinutes -le 20) {
- Sleep (60 * ($Interval / 2))
- }
- else {
- Sleep (60 * ($Interval))
- }
-}
diff --git a/Include.ps1 b/Include.ps1
deleted file mode 100644
index 1f4fad5dc5..0000000000
--- a/Include.ps1
+++ /dev/null
@@ -1,1284 +0,0 @@
-<#
-Copyright (c) 2018-2019 Nemo and MrPlus
-NemosMiner is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-NemosMiner is distributed in the hope that it will be useful, See the
-GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-#>
-
-<#
-Product: NemosMiner
-File: include.ps1
-version: 3.8.0.0
-version date: 16 May 2019
-#>
-
-# New-Item -Path function: -Name ((Get-FileHash $MyInvocation.MyCommand.path).Hash) -Value {$true} -EA SilentlyContinue | out-null
-# Get-Item function::"$((Get-FileHash $MyInvocation.MyCommand.path).Hash)" | Add-Member @{"File" = $MyInvocation.MyCommand.path} -EA SilentlyContinue
-
-
-Function GetNVIDIADriverVersion {
- ((gwmi win32_VideoController) | select name, description, @{Name = "NVIDIAVersion" ; Expression = { ([regex]"[0-9.]{6}$").match($_.driverVersion).value.Replace(".", "").Insert(3, '.') } } | ? { $_.Description -like "*NVIDIA*" } | select -First 1).NVIDIAVersion
-}
-
-Function Global:RegisterLoaded ($File) {
- New-Item -Path function: -Name script:"$((Get-FileHash (Resolve-Path $File)).Hash)" -Value { $true } -EA SilentlyContinue | Add-Member @{"File" = (Resolve-Path $File).Path } -EA SilentlyContinue
- $Variables.StatusText = "File loaded - $($file) - $((Get-PSCallStack).Command[1])"
-}
-
-Function Global:IsLoaded ($File) {
- $Hash = (Get-FileHash (Resolve-Path $File).Path).hash
- If (Test-Path function::$Hash) {
- $True
- }
- else {
- ls function: | ? { $_.File -eq (Resolve-Path $File).Path } | Remove-Item
- $false
- }
-}
-
-Function Start-IdleTracking {
- # Function tracks how long the system has been idle and controls the paused state
- $Global:IdleRunspace = [runspacefactory]::CreateRunspace()
- $IdleRunspace.Open()
- $IdleRunspace.SessionStateProxy.SetVariable('Config', $Config)
- $IdleRunspace.SessionStateProxy.SetVariable('Variables', $Variables)
- $IdleRunspace.SessionStateProxy.SetVariable('StatusText', $StatusText)
- $IdleRunspace.SessionStateProxy.Path.SetLocation((Split-Path $script:MyInvocation.MyCommand.Path))
- $Global:idlepowershell = [powershell]::Create()
- $idlePowershell.Runspace = $IdleRunspace
- $idlePowershell.AddScript( {
- # No native way to check how long the system has been idle in powershell. Have to use .NET code.
- Add-Type -TypeDefinition @'
-using System;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-namespace PInvoke.Win32 {
- public static class UserInput {
- [DllImport("user32.dll", SetLastError=false)]
- private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
-
- [StructLayout(LayoutKind.Sequential)]
- private struct LASTINPUTINFO {
- public uint cbSize;
- public int dwTime;
- }
-
- public static DateTime LastInput {
- get {
- DateTime bootTime = DateTime.UtcNow.AddMilliseconds(-Environment.TickCount);
- DateTime lastInput = bootTime.AddMilliseconds(LastInputTicks);
- return lastInput;
- }
- }
- public static TimeSpan IdleTime {
- get {
- return DateTime.UtcNow.Subtract(LastInput);
- }
- }
- public static int LastInputTicks {
- get {
- LASTINPUTINFO lii = new LASTINPUTINFO();
- lii.cbSize = (uint)Marshal.SizeOf(typeof(LASTINPUTINFO));
- GetLastInputInfo(ref lii);
- return lii.dwTime;
- }
- }
- }
-}
-'@
- Start-Transcript ".\logs\IdleTracking.log" -Append -Force
- $ProgressPreference = "SilentlyContinue"
- . .\Include.ps1; RegisterLoaded(".\Include.ps1")
- While ($True) {
- if (!(IsLoaded(".\Include.ps1"))) { . .\Include.ps1; RegisterLoaded(".\Include.ps1") }
- if (!(IsLoaded(".\Core.ps1"))) { . .\Core.ps1; RegisterLoaded(".\Core.ps1") }
- $IdleSeconds = [math]::Round(([PInvoke.Win32.UserInput]::IdleTime).TotalSeconds)
-
- # Only do anything if Mine only when idle is turned on
- If ($Config.MineWhenIdle) {
- If ($Variables.Paused) {
- # Check if system has been idle long enough to unpause
- If ($IdleSeconds -gt $Config.IdleSec) {
- $Variables.Paused = $False
- $Variables.RestartCycle = $True
- $Variables.StatusText = "System idle for $IdleSeconds seconds, starting mining..."
- }
- }
- else {
- # Pause if system has become active
- If ($IdleSeconds -lt $Config.IdleSec) {
- $Variables.Paused = $True
- $Variables.RestartCycle = $True
- $Variables.StatusText = "System active, pausing mining..."
- }
- }
- }
- Start-Sleep 1
- }
- } ) | Out-Null
- $Variables | Add-Member -Force @{IdleRunspaceHandle = $idlePowershell.BeginInvoke() }
-}
-
-Function Update-Monitoring {
- # Updates a remote monitoring server, sending this worker's data and pulling data about other workers
-
- # Skip if server and user aren't filled out
- if (!$Config.MonitoringServer) { return }
- if (!$Config.MonitoringUser) { return }
-
- If ($Config.ReportToServer) {
- $Version = "NemosMiner $($Variables.CurrentVersion.ToString())"
- $Status = If ($Variables.Paused) { "Paused" } else { "Running" }
- $RunningMiners = $Variables.ActiveMinerPrograms | Where-Object { $_.Status -eq "Running" }
- # Add the associated object from $Variables.Miners since we need data from that too
- $RunningMiners | Foreach-Object {
- $RunningMiner = $_
- $Miner = $Variables.Miners | Where-Object { $_.Name -eq $RunningMiner.Name -and $_.Path -eq $RunningMiner.Path -and $_.Arguments -eq $RunningMiner.Arguments }
- $_ | Add-Member -Force @{'Miner' = $Miner }
- }
-
- # Build object with just the data we need to send, and make sure to use relative paths so we don't accidentally
- # reveal someone's windows username or other system information they might not want sent
- # For the ones that can be an array, comma separate them
- $Data = $RunningMiners | Foreach-Object {
- $RunningMiner = $_
- [pscustomobject]@{
- Name = $RunningMiner.Name
- Path = Resolve-Path -Relative $RunningMiner.Path
- Type = $RunningMiner.Type -join ','
- Algorithm = $RunningMiner.Algorithms -join ','
- Pool = $RunningMiner.Miner.Pools.PSObject.Properties.Value.Name -join ','
- CurrentSpeed = $RunningMiner.HashRate -join ','
- EstimatedSpeed = $RunningMiner.Miner.HashRates.PSObject.Properties.Value -join ','
- Profit = $RunningMiner.Miner.Profit
- }
- }
- $DataJSON = ConvertTo-Json @($Data)
- # Calculate total estimated profit
- $Profit = [string]([Math]::Round(($data | Measure-Object Profit -Sum).Sum, 8))
-
- # Send the request
- $Body = @{user = $Config.MonitoringUser; worker = $Config.WorkerName; version = $Version; status = $Status; profit = $Profit; data = $DataJSON }
- Try {
- $Response = Invoke-RestMethod -Uri "$($Config.MonitoringServer)/api/report.php" -Method Post -Body $Body -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop
- $Variables.StatusText = "Reporting status to server... $Response"
- }
- Catch {
- $Variables.StatusText = "Unable to send status to $($Config.MonitoringServer)"
- }
- }
-
- If ($Config.ShowWorkerStatus) {
- $Variables.StatusText = "Updating status of workers for $($Config.MonitoringUser)"
- Try {
- $Workers = Invoke-RestMethod -Uri "$($Config.MonitoringServer)/api/workers.php" -Method Post -Body @{user = $Config.MonitoringUser } -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop
- # Calculate some additional properties and format others
- $Workers | Foreach-Object {
- # Convert the unix timestamp to a datetime object, taking into account the local time zone
- $_ | Add-Member -Force @{date = [TimeZone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($_.lastseen)) }
-
- # If a machine hasn't reported in for > 10 minutes, mark it as offline
- $TimeSinceLastReport = New-TimeSpan -Start $_.date -End (Get-Date)
- If ($TimeSinceLastReport.TotalMinutes -gt 10) { $_.status = "Offline" }
- # Show friendly time since last report in seconds, minutes, hours or days
- If ($TimeSinceLastReport.Days -ge 1) {
- $_ | Add-Member -Force @{timesincelastreport = '{0:N0} days ago' -f $TimeSinceLastReport.TotalDays }
- }
- elseif ($TimeSinceLastReport.Hours -ge 1) {
- $_ | Add-Member -Force @{timesincelastreport = '{0:N0} hours ago' -f $TimeSinceLastReport.TotalHours }
- }
- elseif ($TimeSinceLastReport.Minutes -ge 1) {
- $_ | Add-Member -Force @{timesincelastreport = '{0:N0} minutes ago' -f $TimeSinceLastReport.TotalMinutes }
- }
- else {
- $_ | Add-Member -Force @{timesincelastreport = '{0:N0} seconds ago' -f $TimeSinceLastReport.TotalSeconds }
- }
- }
-
- $Variables | Add-Member -Force @{Workers = $Workers }
- $Variables | Add-Member -Force @{WorkersLastUpdated = (Get-Date) }
- }
- Catch {
- $Variables.StatusText = "Unable to retrieve worker data from $($Config.MonitoringServer)"
- }
- $Variables | Export-CliXml variables.xml
- }
-}
-
-Function Start-Mining {
- # Starts the runspace that runs NPMCycle
- $Global:CycleRunspace = [runspacefactory]::CreateRunspace()
- $CycleRunspace.Open()
- $CycleRunspace.SessionStateProxy.SetVariable('Config', $Config)
- $CycleRunspace.SessionStateProxy.SetVariable('Variables', $Variables)
- $CycleRunspace.SessionStateProxy.SetVariable('StatusText', $StatusText)
- $CycleRunspace.SessionStateProxy.Path.SetLocation((Split-Path $script:MyInvocation.MyCommand.Path))
- $Global:powershell = [powershell]::Create()
- $powershell.Runspace = $CycleRunspace
- $powershell.AddScript( {
- Start-Transcript ".\logs\CoreCyle.log" -Append -Force
- $ProgressPreference = "SilentlyContinue"
- . .\Include.ps1; RegisterLoaded(".\Include.ps1")
- Update-Monitoring
- While ($True) {
- if (!(IsLoaded(".\Include.ps1"))) { . .\Include.ps1; RegisterLoaded(".\Include.ps1") }
- if (!(IsLoaded(".\Core.ps1"))) { . .\Core.ps1; RegisterLoaded(".\Core.ps1") }
- If ($Variables.Paused) {
- # Run a dummy cycle to keep the UI updating.
-
- # Keep updating exchange rate
- $Rates = Invoke-RestMethod "https://api.coinbase.com/v2/exchange-rates?currency=BTC" -TimeoutSec 15 -UseBasicParsing | Select-Object -ExpandProperty data | Select-Object -ExpandProperty rates
- $Config.Currency | Where-Object { $Rates.$_ } | ForEach-Object { $Rates | Add-Member $_ ([Double]$Rates.$_) -Force }
- $Variables | Add-Member -Force @{Rates = $Rates }
-
- # Update the UI every 30 seconds, and the Last 1/6/24hr and text window every 2 minutes
- for ($i = 0; $i -lt 4; $i++) {
- if ($i -eq 3) {
- $Variables | Add-Member -Force @{EndLoop = $True }
- Update-Monitoring
- }
- else {
- $Variables | Add-Member -Force @{EndLoop = $False }
- }
-
- $Variables.StatusText = "Mining paused"
- Start-Sleep 30
- }
- }
- else {
- NPMCycle
- Update-Monitoring
- Sleep $Variables.TimeToSleep
- }
- }
- }) | Out-Null
- $Variables | add-Member -Force @{CycleRunspaceHandle = $powershell.BeginInvoke() }
-}
-
-Function Stop-Mining {
- # Kills any active miners and stops the runspace that hosts NPMCycle
- If ($Variables.ActiveMinerPrograms) {
- $Variables.ActiveMinerPrograms | ForEach {
- [Array]$filtered = ($BestMiners_Combo | Where Path -EQ $_.Path | Where Arguments -EQ $_.Arguments)
- if ($filtered.Count -eq 0) {
- if ($_.Process -eq $null) {
- $_.Status = "Failed"
- }
- elseif ($_.Process.HasExited -eq $false) {
- $_.Active += (Get-Date) - $_.Process.StartTime
- $_.Process.CloseMainWindow() | Out-Null
- Sleep 1
- # simply "Kill with power"
- Stop-Process $_.Process -Force | Out-Null
- # Try to kill any process with the same path, in case it is still running but the process handle is incorrect
- $KillPath = $_.Path
- Get-Process | Where-Object { $_.Path -eq $KillPath } | Stop-Process -Force
- Write-Host -ForegroundColor Yellow "closing miner"
- Sleep 1
- $_.Status = "Idle"
- }
- }
- }
- }
-
- $Global:CycleRunspace.Close()
- $Global:powershell.Dispose()
-}
-
-Function Update-Status ($Text) {
- $Text | out-host
- # $Variables.StatusText = $Text
- $LabelStatus.Lines += $Text
- If ($LabelStatus.Lines.Count -gt 20) { $LabelStatus.Lines = $LabelStatus.Lines[($LabelStatus.Lines.count - 10)..$LabelStatus.Lines.Count] }
- $LabelStatus.SelectionStart = $LabelStatus.TextLength;
- $LabelStatus.ScrollToCaret();
- $LabelStatus.Refresh | out-null
-}
-
-Function Update-Notifications ($Text) {
- $LabelNotifications.Lines += $Text
- If ($LabelNotifications.Lines.Count -gt 20) { $LabelNotifications.Lines = $LabelNotifications.Lines[($LabelNotifications.Lines.count - 10)..$LabelNotifications.Lines.Count] }
- $LabelNotifications.SelectionStart = $LabelStatus.TextLength;
- $LabelNotifications.ScrollToCaret();
- $LabelStatus.Refresh | out-null
-}
-
-Function DetectGPUCount {
- Update-Status("Fetching GPU Count")
- try {
- $DetectedGPU = @(Get-WmiObject Win32_PnPSignedDriver | Select DeviceName, DriverVersion, Manufacturer, DeviceClass | Where { $_.Manufacturer -like "*NVIDIA*" -and $_.DeviceClass -like "*display*" })
- }
- catch { $DetectedGPU = @() }
- $DetectedGPUCount = $DetectedGPU.Count
- # $DetectedGPUCount = @(Get-WmiObject Win32_PnPSignedDriver | Select DeviceName,DriverVersion,Manufacturer,DeviceClass | Where { $_.Manufacturer -like "*NVIDIA*" -and $_.DeviceClass -like "*display*"}).count } catch { $DetectedGPUCount = 0}
- $i = 0
- $DetectedGPU | foreach { Update-Status("$($i): $($_.DeviceName)") | Out-Null; $i++ }
- Update-Status("Found $($DetectedGPUCount) GPU(s)")
- $DetectedGPUCount
-}
-
-Function Load-Config {
- param(
- [Parameter(Mandatory = $true)]
- [String]$ConfigFile
- )
- If (Test-Path $ConfigFile) {
- $ConfigLoad = Get-Content $ConfigFile | ConvertFrom-json
- $Config = [hashtable]::Synchronized(@{ }); $configLoad | % { $_.psobject.properties | sort Name | % { $Config | Add-Member -Force @{$_.Name = $_.Value } } }
- $Config
- }
-}
-
-Function Write-Config {
- param(
- [Parameter(Mandatory = $true)]
- [PSCustomObject]$Config,
- [Parameter(Mandatory = $true)]
- [String]$ConfigFile
- )
- If ($Config.ManualConfig) { Update-Status("Manual config mode - Not saving config"); return }
- If ($Config -ne $null) {
- if (Test-Path $ConfigFile) { Copy-Item $ConfigFile "$($ConfigFile).backup" }
- $OrderedConfig = [PSCustomObject]@{ }; ($config | select -Property * -ExcludeProperty PoolsConfig) | % { $_.psobject.properties | sort Name | % { $OrderedConfig | Add-Member -Force @{$_.Name = $_.Value } } }
- $OrderedConfig | ConvertTo-json | out-file $ConfigFile
- $PoolsConfig = Get-Content ".\Config\PoolsConfig.json" | ConvertFrom-Json
- $OrderedPoolsConfig = [PSCustomObject]@{ }; $PoolsConfig | % { $_.psobject.properties | sort Name | % { $OrderedPoolsConfig | Add-Member -Force @{$_.Name = $_.Value } } }
- $OrderedPoolsConfig.default | Add-member -Force @{Wallet = $Config.Wallet }
- $OrderedPoolsConfig.default | Add-member -Force @{UserName = $Config.UserName }
- $OrderedPoolsConfig.default | Add-member -Force @{WorkerName = $Config.WorkerName }
- $OrderedPoolsConfig.default | Add-member -Force @{APIKey = $Config.APIKey }
- $OrderedPoolsConfig | ConvertTo-json | out-file ".\Config\PoolsConfig.json"
- }
-}
-
-Function Get-FreeTcpPort ($StartPort) {
- # While ($Port -le ($StartPort + 10) -and !$PortFound) {try{$Null = New-Object System.Net.Sockets.TCPClient -ArgumentList 127.0.0.1,$Port;$Port++} catch {$Port;$PortFound=$True}}
- # $UsedPorts = (Get-NetTCPConnection | ? {$_.state -eq "listen"}).LocalPort
- # While ($StartPort -in $UsedPorts) {
- While (Get-NetTCPConnection -LocalPort $StartPort -EA SilentlyContinue) { $StartPort++ }
- $StartPort
-}
-
-function Set-Stat {
- param(
- [Parameter(Mandatory = $true)]
- [String]$Name,
- [Parameter(Mandatory = $true)]
- [Double]$Value,
- [Parameter(Mandatory = $false)]
- [DateTime]$Date = (Get-Date)
- )
-
- $Path = "Stats\$Name.txt"
- $Date = $Date.ToUniversalTime()
- $SmallestValue = 1E-20
-
- $Stat = [PSCustomObject]@{
- Live = $Value
- Minute = $Value
- Minute_Fluctuation = 1 / 2
- Minute_5 = $Value
- Minute_5_Fluctuation = 1 / 2
- Minute_10 = $Value
- Minute_10_Fluctuation = 1 / 2
- Hour = $Value
- Hour_Fluctuation = 1 / 2
- Day = $Value
- Day_Fluctuation = 1 / 2
- Week = $Value
- Week_Fluctuation = 1 / 2
- Updated = $Date
- }
-
- if (Test-Path $Path) { $Stat = Get-Content $Path | ConvertFrom-Json }
-
- $Stat = [PSCustomObject]@{
- Live = [Double]$Stat.Live
- Minute = [Double]$Stat.Minute
- Minute_Fluctuation = [Double]$Stat.Minute_Fluctuation
- Minute_5 = [Double]$Stat.Minute_5
- Minute_5_Fluctuation = [Double]$Stat.Minute_5_Fluctuation
- Minute_10 = [Double]$Stat.Minute_10
- Minute_10_Fluctuation = [Double]$Stat.Minute_10_Fluctuation
- Hour = [Double]$Stat.Hour
- Hour_Fluctuation = [Double]$Stat.Hour_Fluctuation
- Day = [Double]$Stat.Day
- Day_Fluctuation = [Double]$Stat.Day_Fluctuation
- Week = [Double]$Stat.Week
- Week_Fluctuation = [Double]$Stat.Week_Fluctuation
- Updated = [DateTime]$Stat.Updated
- }
-
- $Span_Minute = [Math]::Min(($Date - $Stat.Updated).TotalMinutes, 1)
- $Span_Minute_5 = [Math]::Min((($Date - $Stat.Updated).TotalMinutes / 5), 1)
- $Span_Minute_10 = [Math]::Min((($Date - $Stat.Updated).TotalMinutes / 10), 1)
- $Span_Hour = [Math]::Min(($Date - $Stat.Updated).TotalHours, 1)
- $Span_Day = [Math]::Min(($Date - $Stat.Updated).TotalDays, 1)
- $Span_Week = [Math]::Min((($Date - $Stat.Updated).TotalDays / 7), 1)
-
- $Stat = [PSCustomObject]@{
- Live = $Value
- Minute = ((1 - $Span_Minute) * $Stat.Minute) + ($Span_Minute * $Value)
- Minute_Fluctuation = ((1 - $Span_Minute) * $Stat.Minute_Fluctuation) +
- ($Span_Minute * ([Math]::Abs($Value - $Stat.Minute) / [Math]::Max([Math]::Abs($Stat.Minute), $SmallestValue)))
- Minute_5 = ((1 - $Span_Minute_5) * $Stat.Minute_5) + ($Span_Minute_5 * $Value)
- Minute_5_Fluctuation = ((1 - $Span_Minute_5) * $Stat.Minute_5_Fluctuation) +
- ($Span_Minute_5 * ([Math]::Abs($Value - $Stat.Minute_5) / [Math]::Max([Math]::Abs($Stat.Minute_5), $SmallestValue)))
- Minute_10 = ((1 - $Span_Minute_10) * $Stat.Minute_10) + ($Span_Minute_10 * $Value)
- Minute_10_Fluctuation = ((1 - $Span_Minute_10) * $Stat.Minute_10_Fluctuation) +
- ($Span_Minute_10 * ([Math]::Abs($Value - $Stat.Minute_10) / [Math]::Max([Math]::Abs($Stat.Minute_10), $SmallestValue)))
- Hour = ((1 - $Span_Hour) * $Stat.Hour) + ($Span_Hour * $Value)
- Hour_Fluctuation = ((1 - $Span_Hour) * $Stat.Hour_Fluctuation) +
- ($Span_Hour * ([Math]::Abs($Value - $Stat.Hour) / [Math]::Max([Math]::Abs($Stat.Hour), $SmallestValue)))
- Day = ((1 - $Span_Day) * $Stat.Day) + ($Span_Day * $Value)
- Day_Fluctuation = ((1 - $Span_Day) * $Stat.Day_Fluctuation) +
- ($Span_Day * ([Math]::Abs($Value - $Stat.Day) / [Math]::Max([Math]::Abs($Stat.Day), $SmallestValue)))
- Week = ((1 - $Span_Week) * $Stat.Week) + ($Span_Week * $Value)
- Week_Fluctuation = ((1 - $Span_Week) * $Stat.Week_Fluctuation) +
- ($Span_Week * ([Math]::Abs($Value - $Stat.Week) / [Math]::Max([Math]::Abs($Stat.Week), $SmallestValue)))
- Updated = $Date
- }
-
- if (-not (Test-Path "Stats")) { New-Item "Stats" -ItemType "directory" }
- [PSCustomObject]@{
- Live = [Decimal]$Stat.Live
- Minute = [Decimal]$Stat.Minute
- Minute_Fluctuation = [Double]$Stat.Minute_Fluctuation
- Minute_5 = [Decimal]$Stat.Minute_5
- Minute_5_Fluctuation = [Double]$Stat.Minute_5_Fluctuation
- Minute_10 = [Decimal]$Stat.Minute_10
- Minute_10_Fluctuation = [Double]$Stat.Minute_10_Fluctuation
- Hour = [Decimal]$Stat.Hour
- Hour_Fluctuation = [Double]$Stat.Hour_Fluctuation
- Day = [Decimal]$Stat.Day
- Day_Fluctuation = [Double]$Stat.Day_Fluctuation
- Week = [Decimal]$Stat.Week
- Week_Fluctuation = [Double]$Stat.Week_Fluctuation
- Updated = [DateTime]$Stat.Updated
- } | ConvertTo-Json | Set-Content $Path
-
- $Stat
-}
-
-function Get-Stat {
- param(
- [Parameter(Mandatory = $true)]
- [String]$Name
- )
-
- if (-not (Test-Path "Stats")) { New-Item "Stats" -ItemType "directory" }
- Get-ChildItem "Stats" | Where-Object Extension -NE ".ps1" | Where-Object BaseName -EQ $Name | Get-Content | ConvertFrom-Json
-}
-
-function Get-ChildItemContent {
- param(
- [Parameter(Mandatory = $true)]
- [String]$Path,
- [Parameter(Mandatory = $false)]
- [Array]$Include = @()
- )
-
- $ChildItems = Get-ChildItem -Recurse -Path $Path -Include $Include | ForEach-Object {
- $Name = $_.BaseName
- $FileName = $_.Name
- $Content = @()
- if ($_.Extension -eq ".ps1") {
- $Content = &$_.FullName
- }
- else {
- Try {
- $Content = $_ | Get-Content | ConvertFrom-Json
- }
- Catch {
- Write-Host "Unable to load $Path\$FileName"
- }
- }
- $Content | ForEach-Object {
- [PSCustomObject]@{Name = $Name; Content = $_ }
- }
- }
-
- $ChildItems | ForEach-Object {
- $Item = $_
- $ItemKeys = $Item.Content.PSObject.Properties.Name.Clone()
- $ItemKeys | ForEach-Object {
- if ($Item.Content.$_ -is [String]) {
- $Item.Content.$_ = Invoke-Expression "`"$($Item.Content.$_)`""
- }
- elseif ($Item.Content.$_ -is [PSCustomObject]) {
- $Property = $Item.Content.$_
- $PropertyKeys = $Property.PSObject.Properties.Name
- $PropertyKeys | ForEach-Object {
- if ($Property.$_ -is [String]) {
- $Property.$_ = Invoke-Expression "`"$($Property.$_)`""
- }
- }
- }
- }
- }
-
- $ChildItems
-}
-function Invoke_TcpRequest {
-
- param(
- [Parameter(Mandatory = $true)]
- [String]$Server = "localhost",
- [Parameter(Mandatory = $true)]
- [String]$Port,
- [Parameter(Mandatory = $true)]
- [String]$Request,
- [Parameter(Mandatory = $true)]
- [Int]$Timeout = 10 #seconds
- )
-
- try {
- $Client = New-Object System.Net.Sockets.TcpClient $Server, $Port
- $Stream = $Client.GetStream()
- $Writer = New-Object System.IO.StreamWriter $Stream
- $Reader = New-Object System.IO.StreamReader $Stream
- $client.SendTimeout = $Timeout * 1000
- $client.ReceiveTimeout = $Timeout * 1000
- $Writer.AutoFlush = $true
-
- $Writer.WriteLine($Request)
- $Response = $Reader.ReadLine()
- }
- catch { $Error.Remove($error[$Error.Count - 1]) }
- finally {
- if ($Reader) { $Reader.Close() }
- if ($Writer) { $Writer.Close() }
- if ($Stream) { $Stream.Close() }
- if ($Client) { $Client.Close() }
- }
-
- $response
-
-}
-
-
-
-#************************************************************************************************************************************************************************************
-#************************************************************************************************************************************************************************************
-#************************************************************************************************************************************************************************************
-
-
-
-function Invoke_httpRequest {
-
- param(
- [Parameter(Mandatory = $true)]
- [String]$Server = "localhost",
- [Parameter(Mandatory = $true)]
- [String]$Port,
- [Parameter(Mandatory = $false)]
- [String]$Request,
- [Parameter(Mandatory = $true)]
- [Int]$Timeout = 10 #seconds
- )
-
- try {
-
- $response = Invoke-WebRequest "http://$($Server):$Port$Request" -UseBasicParsing -TimeoutSec $timeout
- }
- catch { $Error.Remove($error[$Error.Count - 1]) }
-
-
- $response
-
-}
-
-
-#************************************************************************************************************************************************************************************
-#************************************************************************************************************************************************************************************
-#************************************************************************************************************************************************************************************
-
-function Get-HashRate {
- param(
- [Parameter(Mandatory = $true)]
- [String]$API,
- [Parameter(Mandatory = $true)]
- [Int]$Port,
- [Parameter(Mandatory = $false)]
- [Object]$Parameters = @{ }
-
- )
-
- $Server = "localhost"
-
- $Multiplier = 1000
- #$Delta = 0.05
- #$Interval = 5
- #$HashRates = @()
- #$HashRates_Dual = @()
-
- try {
- switch ($API) {
-
- "Dtsm" {
- $Request = Invoke_TcpRequest $server $port "empty" 5
- if ($Request -ne "" -and $request -ne $null) {
- $Data = $Request | ConvertFrom-Json | Select-Object -ExpandProperty result
- $HashRate = [Double](($Data.sol_ps) | Measure-Object -Sum).Sum
- }
-
- }
-
- "xgminer" {
- $Message = @{command = "summary"; parameter = "" } | ConvertTo-Json -Compress
- $Request = Invoke_TcpRequest $server $port $Message 5
-
- if ($Request -ne "" -and $request -ne $null) {
- $Data = $Request.Substring($Request.IndexOf("{"), $Request.LastIndexOf("}") - $Request.IndexOf("{") + 1) -replace " ", "_" | ConvertFrom-Json
-
- $HashRate = if ($Data.SUMMARY.HS_5s -ne $null) { [Double]$Data.SUMMARY.HS_5s * [math]::Pow($Multiplier, 0) }
- elseif ($Data.SUMMARY.KHS_5s -ne $null) { [Double]$Data.SUMMARY.KHS_5s * [math]::Pow($Multiplier, 1) }
- elseif ($Data.SUMMARY.MHS_5s -ne $null) { [Double]$Data.SUMMARY.MHS_5s * [math]::Pow($Multiplier, 2) }
- elseif ($Data.SUMMARY.GHS_5s -ne $null) { [Double]$Data.SUMMARY.GHS_5s * [math]::Pow($Multiplier, 3) }
- elseif ($Data.SUMMARY.THS_5s -ne $null) { [Double]$Data.SUMMARY.THS_5s * [math]::Pow($Multiplier, 4) }
- elseif ($Data.SUMMARY.PHS_5s -ne $null) { [Double]$Data.SUMMARY.PHS_5s * [math]::Pow($Multiplier, 5) }
-
- if ($HashRate -eq $null) {
- $HashRate = if ($Data.SUMMARY.HS_av -ne $null) { [Double]$Data.SUMMARY.HS_av * [math]::Pow($Multiplier, 0) }
- elseif ($Data.SUMMARY.KHS_av -ne $null) { [Double]$Data.SUMMARY.KHS_av * [math]::Pow($Multiplier, 1) }
- elseif ($Data.SUMMARY.MHS_av -ne $null) { [Double]$Data.SUMMARY.MHS_av * [math]::Pow($Multiplier, 2) }
- elseif ($Data.SUMMARY.GHS_av -ne $null) { [Double]$Data.SUMMARY.GHS_av * [math]::Pow($Multiplier, 3) }
- elseif ($Data.SUMMARY.THS_av -ne $null) { [Double]$Data.SUMMARY.THS_av * [math]::Pow($Multiplier, 4) }
- elseif ($Data.SUMMARY.PHS_av -ne $null) { [Double]$Data.SUMMARY.PHS_av * [math]::Pow($Multiplier, 5) }
- }
- }
-
- }
-
- "palgin" {
- $Request = Invoke_TcpRequest $server $port "summary" 5
- $Data = $Request -split ";"
- $HashRate = [double]($Data[5] -split '=')[1] * 1000
- }
-
- "ccminer" {
- $Request = Invoke_TcpRequest $server $port "summary" 5
- $Data = $Request -split ";" | ConvertFrom-StringData
- $HashRate = if ([Double]$Data.KHS -ne 0 -or [Double]$Data.ACC -ne 0) { [Double]$Data.KHS * $Multiplier }
- }
-
- "zjazz" {
- $Request = Invoke_TcpRequest $server $port "summary" 10
- $Data = $Request -split ";" | ConvertFrom-StringData -ErrorAction Stop
- $HashRate = [Double]$Data.KHS * 2000000 #Temp fix for nlpool wrong hashrate
- }
-
- "excavator" {
- $Message = @{id = 1; method = "algorithm.list"; params = @() } | ConvertTo-Json -Compress
- $Request = Invoke_TcpRequest $server $port $message 5
-
- if ($Request -ne "" -and $request -ne $null) {
- $Data = ($Request | ConvertFrom-Json).Algorithms
- $HashRate = [Double](($Data.workers.speed) | Measure-Object -Sum).Sum
- }
- }
-
- "ewbf" {
- $Message = @{id = 1; method = "getstat" } | ConvertTo-Json -Compress
- $Request = Invoke_TcpRequest $server $port $message 5
- $Data = $Request | ConvertFrom-Json
- $HashRate = [Double](($Data.result.speed_sps) | Measure-Object -Sum).Sum
- }
-
- "gminer" {
- $Message = @{id = 1; method = "getstat" } | ConvertTo-Json -Compress
- $Request = Invoke_httpRequest $Server $Port "/stat" 5
- $Data = $Request | ConvertFrom-Json
- $HashRate = [Double]($Data.devices.speed | Measure-Object -Sum).Sum
- }
-
- "claymore" {
- $Request = Invoke_httpRequest $Server $Port "" 5
- if ($Request -ne "" -and $request -ne $null) {
- $Data = $Request.Content.Substring($Request.Content.IndexOf("{"), $Request.Content.LastIndexOf("}") - $Request.Content.IndexOf("{") + 1) | ConvertFrom-Json
- $HashRate = [double]$Data.result[2].Split(";")[0] * $Multiplier
- $HashRate_Dual = [double]$Data.result[4].Split(";")[0] * $Multiplier
- }
- }
-
- "nanominer" {
- $Parameters = @{id = 1; jsonrpc = "2.0"; method = "miner_getstat1" } | ConvertTo-Json -Compress
- $Request = Invoke_tcpRequest $Server $Port $Parameters 5
- if ($Request -ne "" -and $request -ne $null) {
- $Data = $Request | ConvertFrom-Json
- $HashRate = [int](($Data.result[2] -split ';')[0]) #* 1000
- }
- }
-
- "ethminer" {
- $Parameters = @{id = 1; jsonrpc = "2.0"; method = "miner_getstat1" } | ConvertTo-Json -Compress
- $Request = Invoke_tcpRequest $Server $Port $Parameters 5
- if ($Request -ne "" -and $request -ne $null) {
- $Data = $Request | ConvertFrom-Json
- $HashRate = [int](($Data.result[2] -split ';')[0]) * 1000
- }
- }
-
- "ClaymoreV2" {
- $Request = Invoke_httpRequest $Server $Port "" 5
- if ($Request -ne "" -and $request -ne $null) {
- $Data = $Request.Content.Substring($Request.Content.IndexOf("{"), $Request.Content.LastIndexOf("}") - $Request.Content.IndexOf("{") + 1) | ConvertFrom-Json
- $HashRate = [double]$Data.result[2].Split(";")[0]
- }
- }
-
- "TTminer" {
-
- $Parameters = @{id = 1; jsonrpc = "2.0"; method = "miner_getstat1" } | ConvertTo-Json -Compress
- $Request = Invoke_tcpRequest $Server $Port $Parameters 5
- if ($Request -ne "" -and $request -ne $null) {
- $Data = $Request | ConvertFrom-Json
- $HashRate = [int](($Data.result[2] -split ';')[0]) #* 1000
- }
- }
-
- "prospector" {
- $Request = Invoke_httpRequest $Server $Port "/api/v0/hashrates" 5
- if ($Request -ne "" -and $request -ne $null) {
- $Data = $Request | ConvertFrom-Json
- $HashRate = [Double]($Data.rate | Measure-Object -Sum).sum
- }
- }
-
- "fireice" {
- $Request = Invoke_httpRequest $Server $Port "/h" 5
- if ($Request -ne "" -and $request -ne $null) {
- $Data = $Request.Content -split "" -match "total*" -split "" -replace "<[^>]*>", ""
- $HashRate = $Data[1]
- if ($HashRate -eq "") { $HashRate = $Data[2] }
- if ($HashRate -eq "") { $HashRate = $Data[3] }
- }
- }
-
- "miniZ" {
- $Message = '{"id":"0", "method":"getstat"}'
- $Request = Invoke_TcpRequest $server $port $message 5
- $Data = $Request | ConvertFrom-Json
- $HashRate = [Double](($Data.result.speed_sps) | Measure-Object -Sum).Sum
- }
-
- "wrapper" {
- $HashRate = ""
- $wrpath = ".\Logs\energi.txt"
- $HashRate = if (test-path -path $wrpath ) {
- Get-Content $wrpath
- $HashRate = ($HashRate -split ',')[0]
- $HashRate = ($HashRate -split '.')[0]
-
- }
- else { $hashrate = 0 }
- }
-
- "castXMR" {
- $Request = Invoke_httpRequest $Server $Port "" 5
- if ($Request -ne "" -and $request -ne $null) {
- $Data = $Request | ConvertFrom-Json
- $HashRate = [Double]($Data.devices.hash_rate | Measure-Object -Sum).Sum / 1000
- }
- }
-
- "XMrig" {
- $Request = Invoke_httpRequest $Server $Port "/api.json" 5
- if ($Request -ne "" -and $request -ne $null) {
- $Data = $Request | ConvertFrom-Json
- $HashRate = [Double]$Data.hashrate.total[0]
- }
- }
-
- "bminer" {
- $Request = Invoke_httpRequest $Server $Port "/api/status" 5
- if ($Request -ne "" -and $request -ne $null) {
- $Data = $Request.content | ConvertFrom-Json
- $HashRate = 0
- $Data.miners | Get-Member -MemberType NoteProperty | ForEach-Object {
- $HashRate += $Data.miners.($_.name).solver.solution_rate
- }
- }
- }
-
- "GrinPro" {
- $Request = Invoke_httpRequest $Server $Port "/api/status" 5
- if ($Request) {
- $Data = $Request | ConvertFrom-Json
- $HashRate = [double](($Data.workers.graphsPerSecond) | Measure-Object -Sum).Sum
- }
- }
-
- "NBMiner" {
- $Request = Invoke_httpRequest $Server $Port "/api/v1/status" 5
- if ($Request) {
- $Data = $Request | ConvertFrom-Json
- $HashRate = [double]$Data.miner.total_hashrate_raw
- }
- }
-
- "LOL" {
- $Request = Invoke_httpRequest $Server $Port "/summary" 5
- if ($Request) {
- $Data = $Request | ConvertFrom-Json
- $HashRate = [Double]$data.Session.Performance_Summary
- }
- }
-
- "nheq" {
- $Request = Invoke_TcpRequest $Server $Port "status" 5
- if ($Request) {
- $Data = $Request | ConvertFrom-Json
- $HashRate = [Double]$Data.result.speed_ips * 1000000
- }
- }
-
- } #end switch
-
- $HashRates = @()
- $HashRates += [double]$HashRate
- $HashRates += [double]$HashRate_Dual
-
- $HashRates
- }
- catch { }
-}
-
-filter ConvertTo-Hash {
- $Hash = $_
- switch ([math]::truncate([math]::log($Hash, [Math]::Pow(1000, 1)))) {
- "-Infinity" { "0 H" }
- 0 { "{0:n2} H" -f ($Hash / [Math]::Pow(1000, 0)) }
- 1 { "{0:n2} KH" -f ($Hash / [Math]::Pow(1000, 1)) }
- 2 { "{0:n2} MH" -f ($Hash / [Math]::Pow(1000, 2)) }
- 3 { "{0:n2} GH" -f ($Hash / [Math]::Pow(1000, 3)) }
- 4 { "{0:n2} TH" -f ($Hash / [Math]::Pow(1000, 4)) }
- Default { "{0:n2} PH" -f ($Hash / [Math]::Pow(1000, 5)) }
- }
-}
-
-function Get-Combination {
- param(
- [Parameter(Mandatory = $true)]
- [Array]$Value,
- [Parameter(Mandatory = $false)]
- [Int]$SizeMax = $Value.Count,
- [Parameter(Mandatory = $false)]
- [Int]$SizeMin = 1
- )
-
- $Combination = [PSCustomObject]@{ }
-
- for ($i = 0; $i -lt $Value.Count; $i++) {
- $Combination | Add-Member @{[Math]::Pow(2, $i) = $Value[$i] }
- }
-
- $Combination_Keys = $Combination | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name
-
- for ($i = $SizeMin; $i -le $SizeMax; $i++) {
- $x = [Math]::Pow(2, $i) - 1
-
- while ($x -le [Math]::Pow(2, $Value.Count) - 1) {
- [PSCustomObject]@{Combination = $Combination_Keys | Where-Object { $_ -band $x } | ForEach-Object { $Combination.$_ } }
- $smallest = ($x -band - $x)
- $ripple = $x + $smallest
- $new_smallest = ($ripple -band - $ripple)
- $ones = (($new_smallest / $smallest) -shr 1) - 1
- $x = $ripple -bor $ones
- }
- }
-}
-
-function Start-SubProcess {
- param(
- [Parameter(Mandatory = $true)]
- [String]$FilePath,
- [Parameter(Mandatory = $false)]
- [String]$ArgumentList = "",
- [Parameter(Mandatory = $false)]
- [String]$WorkingDirectory = ""
- )
-
- $Job = Start-Job -ArgumentList $PID, $FilePath, $ArgumentList, $WorkingDirectory {
- param($ControllerProcessID, $FilePath, $ArgumentList, $WorkingDirectory)
-
- $ControllerProcess = Get-Process -Id $ControllerProcessID
- if ($ControllerProcess -eq $null) { return }
-
- Add-Type -TypeDefinition @"
- // http://www.daveamenta.com/2013-08/powershell-start-process-without-taking-focus/
-
- using System;
- using System.Diagnostics;
- using System.Runtime.InteropServices;
-
- [StructLayout(LayoutKind.Sequential)]
- public struct PROCESS_INFORMATION {
- public IntPtr hProcess;
- public IntPtr hThread;
- public uint dwProcessId;
- public uint dwThreadId;
- }
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct STARTUPINFO {
- public uint cb;
- public string lpReserved;
- public string lpDesktop;
- public string lpTitle;
- public uint dwX;
- public uint dwY;
- public uint dwXSize;
- public uint dwYSize;
- public uint dwXCountChars;
- public uint dwYCountChars;
- public uint dwFillAttribute;
- public STARTF dwFlags;
- public ShowWindow wShowWindow;
- public short cbReserved2;
- public IntPtr lpReserved2;
- public IntPtr hStdInput;
- public IntPtr hStdOutput;
- public IntPtr hStdError;
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct SECURITY_ATTRIBUTES {
- public int length;
- public IntPtr lpSecurityDescriptor;
- public bool bInheritHandle;
- }
-
- [Flags]
- public enum CreationFlags : int {
- NONE = 0,
- DEBUG_PROCESS = 0x00000001,
- DEBUG_ONLY_THIS_PROCESS = 0x00000002,
- CREATE_SUSPENDED = 0x00000004,
- DETACHED_PROCESS = 0x00000008,
- CREATE_NEW_CONSOLE = 0x00000010,
- CREATE_NEW_PROCESS_GROUP = 0x00000200,
- CREATE_UNICODE_ENVIRONMENT = 0x00000400,
- CREATE_SEPARATE_WOW_VDM = 0x00000800,
- CREATE_SHARED_WOW_VDM = 0x00001000,
- CREATE_PROTECTED_PROCESS = 0x00040000,
- EXTENDED_STARTUPINFO_PRESENT = 0x00080000,
- CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
- CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
- CREATE_DEFAULT_ERROR_MODE = 0x04000000,
- CREATE_NO_WINDOW = 0x08000000,
- }
-
- [Flags]
- public enum STARTF : uint {
- STARTF_USESHOWWINDOW = 0x00000001,
- STARTF_USESIZE = 0x00000002,
- STARTF_USEPOSITION = 0x00000004,
- STARTF_USECOUNTCHARS = 0x00000008,
- STARTF_USEFILLATTRIBUTE = 0x00000010,
- STARTF_RUNFULLSCREEN = 0x00000020, // ignored for non-x86 platforms
- STARTF_FORCEONFEEDBACK = 0x00000040,
- STARTF_FORCEOFFFEEDBACK = 0x00000080,
- STARTF_USESTDHANDLES = 0x00000100,
- }
-
- public enum ShowWindow : short {
- SW_HIDE = 0,
- SW_SHOWNORMAL = 1,
- SW_NORMAL = 1,
- SW_SHOWMINIMIZED = 2,
- SW_SHOWMAXIMIZED = 3,
- SW_MAXIMIZE = 3,
- SW_SHOWNOACTIVATE = 4,
- SW_SHOW = 5,
- SW_MINIMIZE = 6,
- SW_SHOWMINNOACTIVE = 7,
- SW_SHOWNA = 8,
- SW_RESTORE = 9,
- SW_SHOWDEFAULT = 10,
- SW_FORCEMINIMIZE = 11,
- SW_MAX = 11
- }
-
- public static class Kernel32 {
- [DllImport("kernel32.dll", SetLastError=true)]
- public static extern bool CreateProcess(
- string lpApplicationName,
- string lpCommandLine,
- ref SECURITY_ATTRIBUTES lpProcessAttributes,
- ref SECURITY_ATTRIBUTES lpThreadAttributes,
- bool bInheritHandles,
- CreationFlags dwCreationFlags,
- IntPtr lpEnvironment,
- string lpCurrentDirectory,
- ref STARTUPINFO lpStartupInfo,
- out PROCESS_INFORMATION lpProcessInformation);
- }
-"@
- $lpApplicationName = $FilePath;
- $lpCommandLine = '"' + $FilePath + '"' #Windows paths cannot contain ", so there is no need to escape
- if ($ArgumentList -ne "") { $lpCommandLine += " " + $ArgumentList }
- $lpProcessAttributes = New-Object SECURITY_ATTRIBUTES
- $lpProcessAttributes.Length = [System.Runtime.InteropServices.Marshal]::SizeOf($lpProcessAttributes)
- $lpThreadAttributes = New-Object SECURITY_ATTRIBUTES
- $lpThreadAttributes.Length = [System.Runtime.InteropServices.Marshal]::SizeOf($lpThreadAttributes)
- $bInheritHandles = $false
- $dwCreationFlags = [CreationFlags]::CREATE_NEW_CONSOLE
- $lpEnvironment = [IntPtr]::Zero
- if ($WorkingDirectory -ne "") { $lpCurrentDirectory = $WorkingDirectory } else { $lpCurrentDirectory = $pwd }
- $lpStartupInfo = New-Object STARTUPINFO
- $lpStartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($lpStartupInfo)
- $lpStartupInfo.wShowWindow = [ShowWindow]::SW_SHOWMINNOACTIVE
- $lpStartupInfo.dwFlags = [STARTF]::STARTF_USESHOWWINDOW
- $lpProcessInformation = New-Object PROCESS_INFORMATION
-
- $CreateProcessExitCode = [Kernel32]::CreateProcess($lpApplicationName, $lpCommandLine, [ref] $lpProcessAttributes, [ref] $lpThreadAttributes, $bInheritHandles, $dwCreationFlags, $lpEnvironment, $lpCurrentDirectory, [ref] $lpStartupInfo, [ref] $lpProcessInformation)
- $x = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
- Write-Host "CreateProcessExitCode: $CreateProcessExitCode"
- Write-Host "Last error $x"
- Write-Host $lpCommandLine
- Write-Host "lpProcessInformation.dwProcessID: $($lpProcessInformation.dwProcessID)"
-
- If ($CreateProcessExitCode) {
- Write-Host "lpProcessInformation.dwProcessID - WHEN TRUE: $($lpProcessInformation.dwProcessID)"
-
- $Process = Get-Process -Id $lpProcessInformation.dwProcessID
-
- # Dirty workaround
- # Need to investigate. lpProcessInformation sometimes comes null even if process started
- # So getting process with the same FilePath if so
- $Tries = 0
- While ($Process -eq $null -and $Tries -le 5) {
- Write-Host "Can't get process - $Tries"
- $Tries++
- Sleep 1
- $Process = (Get-Process | ? { $_.Path -eq $FilePath })[0]
- Write-Host "Process= $($Process.Handle)"
- }
-
- if ($Process -eq $null) {
- Write-Host "Case 2 - Failed Get-Process"
- [PSCustomObject]@{ProcessId = $null }
- return
- }
- }
- else {
- Write-Host "Case 1 - Failed CreateProcess"
- [PSCustomObject]@{ProcessId = $null }
- return
- }
-
- [PSCustomObject]@{ProcessId = $Process.Id; ProcessHandle = $Process.Handle }
-
- $ControllerProcess.Handle | Out-Null
- $Process.Handle | Out-Null
-
- do { if ($ControllerProcess.WaitForExit(1000)) { $Process.CloseMainWindow() | Out-Null } }
- while ($Process.HasExited -eq $false)
- }
-
- do { Start-Sleep 1; $JobOutput = Receive-Job $Job }
- while ($JobOutput -eq $null)
-
- $Process = Get-Process | Where-Object Id -EQ $JobOutput.ProcessId
- $Process.Handle | Out-Null
- $Process
-}
-
-
-
-
-function Expand-WebRequest {
- param(
- [Parameter(Mandatory = $true)]
- [String]$Uri,
- [Parameter(Mandatory = $true)]
- [String]$Path
- )
-
- $FolderName_Old = ([IO.FileInfo](Split-Path $Uri -Leaf)).BaseName
- $FolderName_New = Split-Path $Path -Leaf
- $FileName = "$FolderName_New$(([IO.FileInfo](Split-Path $Uri -Leaf)).Extension)"
-
- if (Test-Path $FileName) { Remove-Item $FileName }
- if (Test-Path "$(Split-Path $Path)\$FolderName_New") { Remove-Item "$(Split-Path $Path)\$FolderName_New" -Recurse }
- if (Test-Path "$(Split-Path $Path)\$FolderName_Old") { Remove-Item "$(Split-Path $Path)\$FolderName_Old" -Recurse }
-
- Invoke-WebRequest $Uri -OutFile $FileName -TimeoutSec 15 -UseBasicParsing
- Start-Process "7z" "x $FileName -o$(Split-Path $Path)\$FolderName_Old -y -spe" -Wait
- if (Get-ChildItem "$(Split-Path $Path)\$FolderName_Old" | Where-Object PSIsContainer -EQ $false) {
- Rename-Item "$(Split-Path $Path)\$FolderName_Old" "$FolderName_New"
- }
- else {
- Get-ChildItem "$(Split-Path $Path)\$FolderName_Old" | Where-Object PSIsContainer -EQ $true | ForEach-Object { Move-Item "$(Split-Path $Path)\$FolderName_Old\$_" "$(Split-Path $Path)\$FolderName_New" }
- Remove-Item "$(Split-Path $Path)\$FolderName_Old"
- }
- Remove-item $FileName
-}
-
-function Get-Algorithm {
- param(
- [Parameter(Mandatory = $true)]
- [String]$Algorithm
- )
-
- $Algorithms = Get-Content "Algorithms.txt" | ConvertFrom-Json
-
- $Algorithm = (Get-Culture).TextInfo.ToTitleCase(($Algorithm -replace "-", " " -replace "_", " ")) -replace " "
-
- if ($Algorithms.$Algorithm) { $Algorithms.$Algorithm }
- else { $Algorithm }
-}
-
-function Get-Location {
- param(
- [Parameter(Mandatory = $true)]
- [String]$Location
- )
-
- $Locations = Get-Content "Locations.txt" | ConvertFrom-Json
-
- $Location = (Get-Culture).TextInfo.ToTitleCase(($Location -replace "-", " " -replace "_", " ")) -replace " "
-
- if ($Locations.$Location) { $Locations.$Location }
- else { $Location }
-}
-
-Function Autoupdate {
- # GitHub Supporting only TLSv1.2 on feb 22 2018
- [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"
- Set-Location (Split-Path $script:MyInvocation.MyCommand.Path)
- Write-host (Split-Path $script:MyInvocation.MyCommand.Path)
- Update-Status("Checking AutoUpdate")
- Update-Notifications("Checking AutoUpdate")
- # write-host "Checking autoupdate"
- $NemosMinerFileHash = (Get-FileHash ".\NemosMiner.ps1").Hash
- try {
- $AutoUpdateVersion = Invoke-WebRequest "https://nemosminer.com/data/autoupdate.json" -TimeoutSec 15 -UseBasicParsing -Headers @{"Cache-Control" = "no-cache" } | ConvertFrom-Json
- }
- catch { $AutoUpdateVersion = Get-content ".\Config\AutoUpdateVersion.json" | Convertfrom-json }
- If ($AutoUpdateVersion -ne $null) { $AutoUpdateVersion | ConvertTo-json | Out-File ".\Config\AutoUpdateVersion.json" }
- If ($AutoUpdateVersion.Product -eq $Variables.CurrentProduct -and [Version]$AutoUpdateVersion.Version -gt $Variables.CurrentVersion -and $AutoUpdateVersion.AutoUpdate) {
- Update-Status("Version $($AutoUpdateVersion.Version) available. (You are running $($Variables.CurrentVersion))")
- # Write-host "Version $($AutoUpdateVersion.Version) available. (You are running $($Variables.CurrentVersion))"
- $LabelNotifications.ForeColor = "Green"
- $LabelNotifications.Lines += "Version $([Version]$AutoUpdateVersion.Version) available"
-
- If ($AutoUpdateVersion.Autoupdate) {
- $LabelNotifications.Lines += "Starting Auto Update"
- # Setting autostart to true
- $Config.autostart = $true
- Write-Config -ConfigFile $ConfigFile -Config $Config
-
- # Download update file
- $UpdateFileName = ".\$($AutoUpdateVersion.Product)-$($AutoUpdateVersion.Version)"
- Update-Status("Downloading version $($AutoUpdateVersion.Version)")
- Update-Notifications("Downloading version $($AutoUpdateVersion.Version)")
- try {
- Invoke-WebRequest $AutoUpdateVersion.Uri -OutFile "$($UpdateFileName).zip" -TimeoutSec 15 -UseBasicParsing
- }
- catch { Update-Status("Update download failed"); Update-Notifications("Update download failed"); $LabelNotifications.ForeColor = "Red"; return }
- If (!(test-path ".\$($UpdateFileName).zip")) {
- Update-Status("Cannot find update file")
- Update-Notifications("Cannot find update file")
- $LabelNotifications.ForeColor = "Red"
- return
- }
-
- # Backup current version folder in zip file
- Update-Status("Backing up current version...")
- Update-Notifications("Backing up current version...")
- $BackupFileName = ("AutoupdateBackup-$(Get-Date -Format u).zip").replace(" ", "_").replace(":", "")
- Start-Process "7z" "a $($BackupFileName) .\* -x!*.zip" -Wait -WindowStyle hidden
- If (!(test-path .\$BackupFileName)) { Update-Status("Backup failed"); return }
-
- # Pre update specific actions if any
- # Use PreUpdateActions.ps1 in new release to place code
- If (Test-Path ".\$UpdateFileName\PreUpdateActions.ps1") {
- Invoke-Expression (get-content ".\$UpdateFileName\PreUpdateActions.ps1" -Raw)
- }
-
- # unzip in child folder excluding config
- Update-Status("Unzipping update...")
- Start-Process "7z" "x $($UpdateFileName).zip -o.\ -y -spe -xr!config" -Wait -WindowStyle hidden
-
- # copy files
- Update-Status("Copying files...")
- Copy-Item .\$UpdateFileName\* .\ -force -Recurse
-
- # Remove any obsolete miner file (ie. Not in new version Miners or OptionalMiners)
- ls .\Miners\ | ? { $_.name -notin (ls .\$UpdateFileName\Miners\).name -and $_.name -notin (ls .\$UpdateFileName\OptionalMiners\).name } | % { Remove-Item -Force $_.FullName }
-
- # Post update specific actions if any
- # Use PostUpdateActions.ps1 in new release to place code
- If (Test-Path ".\$UpdateFileName\PostUpdateActions.ps1") {
- Invoke-Expression (get-content ".\$UpdateFileName\PostUpdateActions.ps1" -Raw)
- }
-
- #Remove temp files
- Update-Status("Removing temporary files...")
- Remove-Item .\$UpdateFileName -Force -Recurse
- Remove-Item ".\$($UpdateFileName).zip" -Force
- If (Test-Path ".\PreUpdateActions.ps1") { Remove-Item ".\PreUpdateActions.ps1" -Force }
- If (Test-Path ".\PostUpdateActions.ps1") { Remove-Item ".\PostUpdateActions.ps1" -Force }
- ls "AutoupdateBackup-*.zip" | Where { $_.name -notin (ls "AutoupdateBackup-*.zip" | sort LastWriteTime -Descending | select -First 2).name } | Remove-Item -Force
-
- # Start new instance (Wait and confirm start)
- # Kill old instance
- If ($AutoUpdateVersion.RequireRestart -or ($NemosMinerFileHash -ne (Get-FileHash ".\NemosMiner.ps1").Hash)) {
- Update-Status("Starting Updated Version")
- $StartCommand = ((gwmi win32_process -filter "ProcessID=$PID" | select commandline).CommandLine)
- $NewKid = Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList @($StartCommand, (Split-Path $script:MyInvocation.MyCommand.Path))
- # Giving 10 seconds for process to start
- $Waited = 0
- sleep 10
- While (!(Get-Process -id $NewKid.ProcessId -EA silentlycontinue) -and ($waited -le 10)) { sleep 1; $waited++ }
- If (!(Get-Process -id $NewKid.ProcessId -EA silentlycontinue)) {
- Update-Status("Failed to start new instance of NemosMiner")
- Update-Notifications("NemosMiner auto updated to version $($AutoUpdateVersion.Version) but failed to restart.")
- $LabelNotifications.ForeColor = "Red"
- return
- }
-
- $TempVerObject = (Get-Content .\Version.json | ConvertFrom-Json)
- $TempVerObject | Add-Member -Force @{AutoUpdated = (Get-Date) }
- $TempVerObject | ConvertTo-Json | Out-File .\Version.json
-
- Update-Status("NemosMiner successfully updated to version $($AutoUpdateVersion.Version)")
- Update-Notifications("NemosMiner successfully updated to version $($AutoUpdateVersion.Version)")
-
- Update-Status("Killing myself")
- If (Get-Process -id $NewKid.ProcessId) { Stop-process -id $PID }
- }
- else {
- $TempVerObject = (Get-Content .\Version.json | ConvertFrom-Json)
- $TempVerObject | Add-Member -Force @{AutoUpdated = (Get-Date) }
- $TempVerObject | ConvertTo-Json | Out-File .\Version.json
-
- Update-Status("Successfully updated to version $($AutoUpdateVersion.Version)")
- Update-Notifications("Successfully updated to version $($AutoUpdateVersion.Version)")
- $LabelNotifications.ForeColor = "Green"
- }
- }
- elseif (!($Config.Autostart)) {
- UpdateStatus("Cannot autoupdate as autostart not selected")
- Update-Notifications("Cannot autoupdate as autostart not selected")
- $LabelNotifications.ForeColor = "Red"
- }
- else {
- UpdateStatus("$($AutoUpdateVersion.Product)-$($AutoUpdateVersion.Version). Not candidate for Autoupdate")
- Update-Notifications("$($AutoUpdateVersion.Product)-$($AutoUpdateVersion.Version). Not candidate for Autoupdate")
- $LabelNotifications.ForeColor = "Red"
- }
- }
- else {
- Update-Status("$($AutoUpdateVersion.Product)-$($AutoUpdateVersion.Version). Not candidate for Autoupdate")
- Update-Notifications("$($AutoUpdateVersion.Product)-$($AutoUpdateVersion.Version). Not candidate for Autoupdate")
- $LabelNotifications.ForeColor = "Green"
- }
-}
diff --git a/Includes/API.psm1 b/Includes/API.psm1
new file mode 100644
index 0000000000..9c7655f764
--- /dev/null
+++ b/Includes/API.psm1
@@ -0,0 +1,1003 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: API.psm1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+Function Initialize-API {
+
+ If ($Variables.APIRunspace.AsyncObject.IsCompleted -eq $true) {
+ Stop-APIServer
+ $Variables.Remove("APIVersion")
+ }
+
+ If ($Config.APIPort) {
+
+ # Initialize API & Web GUI
+ If ($Config.APIPort -ne $Variables.APIRunspace.APIPort) {
+
+ Write-Message -Level Verbose "Initializing API & Web GUI on 'http://localhost:$($Config.APIPort)'..."
+
+ $TCPClient = New-Object System.Net.Sockets.TCPClient
+ $AsyncResult = $TCPClient.BeginConnect("localhost", $Config.APIPort, $null, $null)
+ If ($AsyncResult.AsyncWaitHandle.WaitOne(100)) {
+ Write-Message -Level Error "Error initializing API & Web GUI on port $($Config.APIPort). Port is in use."
+ Try { $TCPClient.EndConnect($AsyncResult) = $null }
+ Catch { }
+ }
+ Else {
+ # Start API server
+ Start-APIServer -Port $Config.APIPort
+
+ # Wait for API to get ready
+ $RetryCount = 3
+ While (-not ($Variables.APIVersion) -and $RetryCount -gt 0) {
+ Try {
+ If ($Variables.APIVersion = (Invoke-RestMethod "http://localhost:$($Variables.APIRunspace.APIPort)/apiversion" -UseBasicParsing -TimeoutSec 1 -ErrorAction Stop)) {
+ Write-Message -Level Info "Web GUI and API (version $($Variables.APIVersion)) running on http://localhost:$($Variables.APIRunspace.APIPort)."
+ # Start Web GUI (show config edit if no existing config)
+ If ($Config.WebGui) { Start-Process "http://localhost:$($Variables.APIRunspace.APIPort)/$(If ($Variables.FreshConfig -eq $true) { "configedit.html" })" }
+ Break
+ }
+ }
+ Catch { }
+ $RetryCount--
+ Start-Sleep -Seconds 1
+ }
+ If (-not $Variables.APIVersion) { Write-Message -Level Error "Error initializing API & Web GUI on port $($Config.APIPort)." }
+ Remove-Variable RetryCount
+ }
+ $TCPClient.Close()
+ Remove-Variable AsyncResult
+ Remove-Variable TCPClient
+ }
+ }
+}
+Function Start-APIServer {
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [Int]$Port
+ )
+
+ Stop-APIServer
+
+ $APIVersion = "0.4.5.2"
+
+ If ($Config.APILogFile) { "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss"): API ($APIVersion) started." | Out-File $Config.APILogFile -Encoding utf8NoBOM -Force }
+
+ # Setup runspace to launch the API webserver in a separate thread
+ $APIRunspace = [RunspaceFactory]::CreateRunspace()
+ $APIRunspace.Open()
+ Get-Variable -Scope Global | Where-Object Name -in @("Config", "Stats", "Variables") | ForEach-Object {
+ Try {
+ $APIRunspace.SessionStateProxy.SetVariable($_.Name, $_.Value)
+ }
+ Catch { }
+ }
+
+ $Variables.APIRunspace = $APIRunspace
+ $Variables.APIRunspace | Add-Member -Force @{ APIPort = $Port }
+
+ $Variables.APIRunspace.SessionStateProxy.SetVariable("APIVersion", $APIVersion)
+ $Variables.APIRunspace.SessionStateProxy.Path.SetLocation($Variables.MainPath)
+
+ $PowerShell = [PowerShell]::Create()
+ $PowerShell.Runspace = $APIRunspace
+ $PowerShell.AddScript(
+ {
+ (Get-Process -Id $PID).PriorityClass = "Normal"
+
+ # Set the starting directory
+ $BasePath = "$PWD\web"
+
+ $ScriptBody = "using module .\Includes\Include.psm1"; $Script = [ScriptBlock]::Create($ScriptBody); . $Script
+
+ # List of possible mime types for files
+ $MIMETypes = @{
+ ".js" = "application/x-javascript"
+ ".html" = "text/html"
+ ".htm" = "text/html"
+ ".json" = "application/json"
+ ".css" = "text/css"
+ ".txt" = "text/plain"
+ ".ico" = "image/x-icon"
+ ".ps1" = "text/html" # ps1 files get executed, assume their response is html
+ }
+
+ # Setup the listener
+ $Server = New-Object System.Net.HttpListener
+ $Variables.APIRunspace | Add-Member -Force @{ APIServer = $Server }
+
+ # Listening on anything other than localhost requires admin privileges
+ $Server.Prefixes.Add("http://localhost:$($Variables.APIRunspace.APIPort)/")
+ $Server.Start()
+
+ While ($Server.IsListening) {
+ $Context = $Server.GetContext()
+ $Request = $Context.Request
+
+ # Determine the requested resource and parse query strings
+ $Path = $Request.Url.LocalPath
+
+ If ($Config.APILogFile) { "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss"): $($Request.Url)$($Request.Url.Query)" | Out-File $Config.APILogFile -Append -Encoding utf8NoBOM }
+
+ # Parse any parameters in the URL - $Request.Url.Query looks like "+ ?a=b&c=d&message=Hello%20world"
+ $Parameters = @{ }
+ $Request.Url.Query -replace "\?", "" -split '&' | Foreach-Object {
+ $Key, $Value = $_ -split '='
+ # Decode any url escaped characters in the key and value
+ $Key = [URI]::UnescapeDataString($Key)
+ $Value = [URI]::UnescapeDataString($Value)
+ If ($Key -and $Value) { $Parameters.$Key = $Value }
+ }
+
+ # Create a new response and the defaults for associated settings
+ $Response = $Context.Response
+ $ContentType = "application/json"
+ $StatusCode = 200
+ $Data = ""
+
+ # Set the proper content type, status code and data for each resource
+ Switch ($Path) {
+ "/functions/api/stop" {
+ Return
+ }
+ "/functions/balancedata/remove" {
+ If ($Parameters.Data) {
+ $BalanceDataEntries = ($Parameters.Data | ConvertFrom-Json -ErrorAction SilentlyContinue)
+ $Variables.BalanceData = @((Compare-Object $Variables.BalanceData $BalanceDataEntries -PassThru -Property DateTime, Pool, Currency, Wallet) | Select-Object -ExcludeProperty SideIndicator)
+ $Variables.BalanceData | ConvertTo-Json | Out-File ".\Logs\BalancesTrackerData.json" -ErrorAction Ignore
+ If ($BalanceDataEntries.Count -gt 0) {
+ $Variables.BalanceData | ConvertTo-Json | Out-File ".\Logs\BalancesTrackerData.json" -ErrorAction Ignore
+ $Message = "$($BalanceDataEntries.Count) $(If ($BalanceDataEntries.Count -eq 1) { "balance data entry" } Else { "balance data entries" }) removed."
+ Write-Message -Level Verbose "Web GUI: $Message"
+ $Data += "`n`n$Message"
+ }
+ Else {
+ $Data = "`nNo matching entries found."
+ }
+ $Data = "$Data "
+ Break
+ }
+ }
+ "/functions/config/device/disable" {
+ ForEach ($Key in $Parameters.Keys) {
+ If ($Values = @($Parameters.$Key -split ',' | Where-Object { $_ -notin $Config.ExcludeDeviceName })) {
+ Try {
+ $Data = "`nDevice configuration changed`n`nOld values:"
+ $Data += "`nExcludeDeviceName: '[$($Config."ExcludeDeviceName" -join ', ')]'"
+ $Config.ExcludeDeviceName = @((@($Config.ExcludeDeviceName) + $Values) | Sort-Object -Unique)
+ $Data += "`n`nNew values:"
+ $Data += "`nExcludeDeviceName: '[$($Config."ExcludeDeviceName" -join ', ')]'"
+ $Data += "`n`nUpdated configFile`n$($Variables.ConfigFile)"
+ Write-Config -ConfigFile $Variables.ConfigFile -NewConfig $Config
+ ForEach ($DeviceName in $Values) {
+ $Variables.Devices | Where-Object Name -EQ $DeviceName | ForEach-Object {
+ $_.State = [DeviceState]::Disabled
+ If ($_.Status -like "* {*@*}") { $_.Status = "$($_.Status); will get disabled at end of cycle" }
+ Else { $_.Status = "Disabled (ExcludeDeviceName: '$($_.Name)')" }
+ }
+ }
+ Write-Message -Level Verbose "Web GUI: Device$(If ($Values.Count -ne 1) { "s" } ) '$($Values -join '; ')' disabled. Config file '$($Variables.ConfigFile)' updated."
+ }
+ Catch {
+ $Data = "Error saving config file`n'$($Variables.ConfigFile) $($Error[0])'. "
+ }
+ }
+ Else {
+ $Data = "No configuration change"
+ }
+ }
+ $Data = "$Data "
+ Break
+ }
+ "/functions/config/device/enable" {
+ ForEach ($Key in $Parameters.Keys) {
+ If ($Values = @($Parameters.$Key -split ',' | Where-Object { $_ -in $Config.ExcludeDeviceName })) {
+ Try {
+ $Data = "`nDevice configuration changed`n`nOld values:"
+ $Data += "`nExcludeDeviceName: '[$($Config."ExcludeDeviceName" -join ', ')]'"
+ $Config.ExcludeDeviceName = @($Config.ExcludeDeviceName | Where-Object { $_ -notin $Values } | Sort-Object -Unique)
+ $Data += "`n`nNew values:"
+ $Data += "`nExcludeDeviceName: '[$($Config."ExcludeDeviceName" -join ', ')]'"
+ $Data += "`n`nUpdated configFile`n$($Variables.ConfigFile)"
+ Write-Config -ConfigFile $Variables.ConfigFile -NewConfig $Config
+ $Variables.Devices | Where-Object Name -in $Values | ForEach-Object {
+ $_.State = [DeviceState]::Enabled
+ If ($_.Status -like "* {*@*}; will get disabled at end of cycle") { $_.Status = $_.Status -replace "; will get disabled at end of cycle" }
+ Else { $_.Status = "Idle" }
+ }
+ Write-Message -Level Verbose "Web GUI: Device$(If ($Values.Count -ne 1) { "s" } ) '$($Values -join '; ')' enabled. Config file '$($Variables.ConfigFile)' updated."
+ }
+ Catch {
+ $Data = "Error saving config file`n'$($Variables.ConfigFile) $($Error[0])'. "
+ }
+ }
+ Else {
+ $Data = "No configuration change"
+ }
+ }
+ $Data = "$Data "
+ Break
+ }
+ "/functions/config/set" {
+ Try {
+ Write-Config -ConfigFile $Variables.ConfigFile -NewConfig ($Key | ConvertFrom-Json)
+ Read-Config -ConfigFile $Variables.ConfigFile
+ $Variables.Devices | Select-Object | Where-Object { $_.State -ne [DeviceState]::Unsupported } | ForEach-Object {
+ If ($_.Name -in @($Config.ExcludeDeviceName)) {
+ $_.State = [DeviceState]::Disabled
+ If ($_.Status -like "Mining *}") { $_.Status = "$($_.Status); will get disabled at end of cycle" }
+ }
+ Else {
+ $_.State = [DeviceState]::Enabled
+ If ($_.Status -like "*; will get disabled at end of cycle") { $_.Status = $_.Status -replace "; will get disabled at end of cycle" }
+ If ($_.Status -like "Disabled *") { $_.Status = "Idle" }
+ }
+ }
+ $Variables.RestartCycle = $true
+
+ # Set operational values for text window
+ $Variables.ShowAccuracy = $Config.ShowAccuracy
+ $Variables.ShowAllMiners = $Config.ShowAllMiners
+ $Variables.ShowEarning = $Config.ShowEarning
+ $Variables.ShowEarningBias = $Config.ShowEarningBias
+ $Variables.ShowMinerFee = $Config.ShowMinerFee
+ $Variables.ShowPoolBalances = $Config.ShowPoolBalances
+ $Variables.ShowPoolFee = $Config.ShowPoolFee
+ $Variables.ShowPowerCost = $Config.ShowPowerCost
+ $Variables.ShowPowerUsage = $Config.ShowPowerUsage
+ $Variables.ShowProfit = $Config.ShowProfit
+ $Variables.ShowProfitBias = $Config.ShowProfitBias
+
+ Read-Config -ConfigFile $Variables.ConfigFile
+
+ Write-Message -Level Verbose "Web GUI: Configuration applied."
+ $Data = "Config saved to '$($Variables.ConfigFile)'. It will become active in next cycle."
+ }
+ Catch {
+ $Data = "Error saving config file`n'$($Variables.ConfigFile)'."
+ }
+ $Data = "$Data "
+ Break
+ }
+ "/functions/file/edit" {
+ $Data = Edit-File $Parameters.FileName
+ Break
+ }
+ "/functions/file/showcontent" {
+ $Data = (Get-Content -Path $Parameters.FileName -Raw -ErrorAction Ignore) -replace "(?"
+ Break
+ }
+ "/functions/log/get" {
+ $Lines = If ([Int]$Parameters.Lines) { [Int]$Parameters.Lines } Else { 100 }
+ $Data = " $(Get-Content -Path $Variables.LogFile -Tail $Lines | ForEach-Object { "$($_)`n" } )"
+ Break
+ }
+ "/functions/mining/getstatus" {
+ $Data = If ($Variables.MiningStatus -eq $Variables.NewMiningStatus) { ConvertTo-Json ($Variables.MiningStatus) } Else { ConvertTo-Json ($Variables.NewMiningStatus) }
+ Break
+ }
+ "/functions/mining/pause" {
+ If ($Variables.MiningStatus -ne "Paused") {
+ $Variables.NewMiningStatus = "Paused"
+ $Data = "Mining is being paused...`n$(If ($Variables.BalancesTrackerPollInterval -gt 0) { If (-not $Variables.BalancesTrackerRunspace) { "Balances Tracker starting..." } Else { "Balances Tracker running." } })"
+ $Variables.RestartCycle = $true
+ }
+ $Data = "$Data "
+ Break
+ }
+ "/functions/mining/start" {
+ If ($Variables.MiningStatus -ne "Running") {
+ $Variables.NewMiningStatus = "Running"
+ $Data = "Mining processes starting...`n$(If ($Variables.BalancesTrackerPollInterval -gt 0) { If (-not $Variables.BalancesTrackerRunspace) { "Balances Tracker starting..." } Else { "Balances Tracker running." } })"
+ $Variables.RestartCycle = $true
+ }
+ $Data = "$Data "
+ Break
+ }
+ "/functions/mining/stop" {
+ If ($Variables.MiningStatus -ne "Idle") {
+ $Variables.NewMiningStatus = "Idle"
+ $Data = "$($Variables.Branding.ProductLabel) is getting idle...`n"
+ $Variables.RestartCycle = $true
+ }
+ $Data = "$Data "
+ Break
+ }
+ "/functions/pool/disable" {
+ If ($Parameters.Pools) {
+ $PoolsConfig = Get-Content -Path $Variables.PoolsConfigFile -ErrorAction Ignore | ConvertFrom-Json
+ $Pools = @(($Parameters.Pools | ConvertFrom-Json -ErrorAction SilentlyContinue) | Sort-Object Name, Algorithm -Unique)
+ $Pools | Group-Object Name | ForEach-Object {
+ $PoolName = $_.Name -replace " External$| Internal$"
+ $PoolBaseName = (Get-PoolBaseName $PoolName)
+
+ $PoolConfig = If ($PoolsConfig.$PoolBaseName) { $PoolsConfig.$PoolBaseName } Else { [PSCustomObject]@{ } }
+ [System.Collections.ArrayList]$AlgorithmList = @(($PoolConfig.Algorithm -replace " ") -split ',')
+
+ ForEach ($Algorithm in $_.Group.Algorithm) {
+ $AlgorithmList.Remove("+$Algorithm")
+ If (-not ($AlgorithmList -match "\+.+") -and $AlgorithmList -notcontains "-$Algorithm") { $AlgorithmList += "-$Algorithm" }
+
+ $Reason = "Algorithm disabled (``-$($Algorithm)`` in $PoolBaseName pool config)"
+ $Variables.Pools | Where-Object BaseName -EQ $PoolName | Where-Object Algorithm -EQ $Algorithm | ForEach-Object {
+ $_.Reason = @($_.Reason | Where-Object { $_ -notmatch $Reason })
+ $_.Reason += $Reason
+ $_.Available = $false
+ }
+ $Data += "`n$Algorithm@$PoolName ($((($Variables.Pools | Where-Object Name -EQ $PoolName | Where-Object Algorithm -EQ $Algorithm).Region | Sort-Object -Unique) -join ', '))"
+ }
+
+ If ($AlgorithmList) { $PoolConfig | Add-Member Algorithm (($AlgorithmList | Sort-Object) -join ',' -replace "^,+") -Force } Else { $PoolConfig.PSObject.Properties.Remove('Algorithm') }
+ If (($PoolConfig | Get-Member -MemberType NoteProperty).Name) { $PoolsConfig | Add-Member $PoolBaseName $PoolConfig -Force } Else { $PoolsConfig.PSObject.Properties.Remove($PoolName) }
+ }
+ $DisabledPoolsCount = $Pools.Count
+ If ($DisabledPoolsCount -gt 0) {
+ # Write PoolsConfig
+ $PoolsConfig | Get-SortedObject | ConvertTo-Json -Depth 10 | Set-Content -Path $Variables.PoolsConfigFile -Force -ErrorAction Ignore
+ $Message = "$DisabledPoolsCount $(If ($DisabledPoolsCount -eq 1) { "algorithm" } Else { "algorithms" }) disabled."
+ Write-Message -Level Verbose "Web GUI: $Message"
+ $Data += "`n`n$Message"
+ }
+ Break
+ }
+ }
+ "/functions/pool/enable" {
+ If ($Parameters.Pools) {
+ $PoolsConfig = Get-Content -Path $Variables.PoolsConfigFile -ErrorAction Ignore | ConvertFrom-Json
+ $Pools = @(($Parameters.Pools | ConvertFrom-Json -ErrorAction SilentlyContinue) | Sort-Object Name, Algorithm -Unique)
+ $Pools | Group-Object Name | ForEach-Object {
+ $PoolName = $_.Name -replace " External$| Internal$"
+ $PoolBaseName = (Get-PoolBaseName $PoolName)
+
+ $PoolConfig = If ($PoolsConfig.$PoolBaseName) { $PoolsConfig.$PoolBaseName } Else { [PSCustomObject]@{ } }
+ [System.Collections.ArrayList]$AlgorithmList = @(($PoolConfig.Algorithm -replace " ") -split ',')
+
+ ForEach ($Algorithm in $_.Group.Algorithm) {
+ $AlgorithmList.Remove("-$Algorithm")
+ If ($AlgorithmList -match "\+.+" -and $AlgorithmList -notcontains "+$Algorithm") { $AlgorithmList += "+$Algorithm" }
+
+ $Reason = "Algorithm disabled (``-$($Algorithm)`` in $PoolBaseName pool config)"
+ $Variables.Pools | Where-Object BaseName -EQ $PoolName | Where-Object Algorithm -EQ $Algorithm | ForEach-Object {
+ $_.Reason = @($_.Reason | Where-Object { $_ -ne $Reason })
+ If (-not $_.Reason) { $_.Available = $true }
+ }
+ $Data += "`n$Algorithm@$PoolName ($((($Variables.Pools | Where-Object Name -EQ $PoolName | Where-Object Algorithm -EQ $Algorithm).Region | Sort-Object -Unique) -join ', '))"
+ }
+
+ If ($AlgorithmList) { $PoolConfig | Add-Member Algorithm (($AlgorithmList | Sort-Object) -join ',' -replace "^,+") -Force } Else { $PoolConfig.PSObject.Properties.Remove('Algorithm') }
+ If (($PoolConfig | Get-Member -MemberType NoteProperty).Name) { $PoolsConfig | Add-Member $PoolBaseName $PoolConfig -Force } Else { $PoolsConfig.PSObject.Properties.Remove($PoolName) }
+ }
+ $EnabledPoolsCount = $Pools.Count
+ If ($EnabledPoolsCount -gt 0) {
+ # Write PoolsConfig
+ $PoolsConfig | Get-SortedObject | ConvertTo-Json -Depth 10 | Set-Content -Path $Variables.PoolsConfigFile -Force -ErrorAction Ignore
+ $Message = "$EnabledPoolsCount $(If ($EnabledPoolsCount -eq 1) { "algorithm" } Else { "algorithms" }) enabled."
+ Write-Message -Level Verbose "Web GUI: $Message"
+ $Data += "`n`n$Message"
+ }
+ Break
+ }
+ }
+ "/functions/stat/get" {
+ $TempStats = @(If ($null -ne $Parameters.Value) { @($Stats.Keys | Where-Object { $_ -like "*$($Parameters.Type)" } | Where-Object { $Stats.$_.Live -eq $Parameters.Value } | ForEach-Object { $Stats.$_ }) } Else { @($Stats) })
+
+ If ($TempStats) {
+ If ($null -ne $Parameters.Value) {
+ $TempStats | Sort-Object Name | ForEach-Object { $Data += "`n$($_.Name -replace "_$($Parameters.Type)")" }
+ If ($Parameters.Type -eq "Hashrate") { $Data += "`n`n$($TempStats.Count) stat file$(if ($TempStats.Count -ne 1) { "s" }) with $($Parameters.Value)H/s $($Parameters.Type)." }
+ ElseIf ($Parameters.Type -eq "PowerUsage") { $Data += "`n`n$($TempStats.Count) stat file$(if ($TempStats.Count -ne 1) { "s" }) with $($Parameters.Value)W $($Parameters.Type)." }
+ }
+ Else {
+ $Data = $TempStats | ConvertTo-Json
+ }
+ }
+ Else {
+ $Data = "`nNo matching stats found."
+ }
+ Break
+ }
+ "/functions/removeorphanedminerstats" {
+ If ($StatNames = Remove-OrphanedMinerStats) {
+ $Data = $StatNames | ConvertTo-Json
+ }
+ Else {
+ $Data = "`nNo matching stats found."
+ }
+ Break
+ }
+ "/functions/stat/remove" {
+ If ($Parameters.Pools) {
+ If ($Pools = @(Compare-Object -PassThru -IncludeEqual -ExcludeDifferent @($Variables.Pools | Select-Object) @($Parameters.Pools | ConvertFrom-Json -ErrorAction SilentlyContinue | Select-Object) -Property Algorithm, Currency, Name, Region)) {
+ $Pools | Sort-Object Name | ForEach-Object {
+ $Stat_Name = "$($_.Name)_$($_.Algorithm)$(If ($_.Currency) { "-$($_.Currency)" })"
+ $Data += "`n$($Stat_Name) ($($_.Region))"
+ Remove-Stat -Name "$($Stat_Name)_Profit"
+ $_.Reason = [String[]]@()
+ $_.Price = $_.Price_Bias = $_.StablePrice = $_.Accuracy = [Double]::Nan
+ $_.Available = $true
+ $_.Disabled = $false
+ }
+ $Message = "Reset pool stats for $($Pools.Count) $(If ($Pools.Count -eq 1) { "pool" } Else { "pools" })."
+ Write-Message -Level Verbose "Web GUI: $Message"
+ $Data += "`n`n$Message"
+ }
+ Else {
+ $Data = "`nNo matching pool stats found."
+ }
+ Break
+ }
+ ElseIf ($Parameters.Miners -and $Parameters.Type -eq "HashRate") {
+ If ($Miners = @(Compare-Object -PassThru -IncludeEqual -ExcludeDifferent @($Variables.Miners | Select-Object) @($Parameters.Miners | ConvertFrom-Json -ErrorAction SilentlyContinue | Select-Object) -Property Name, Algorithm)) {
+ $Miners | Sort-Object Name, Algorithm | ForEach-Object {
+ If ($_.Earning -eq 0) { $_.Available = $true }
+ $_.Earning_Accuracy = [Double]::NaN
+ $_.Activated = 0 # To allow 3 attempts
+ $_.Disabled = $false
+ $_.Benchmark = $true
+ $_.Restart = $true
+ $_.Workers | ForEach-Object { $_.Speed = [Double]::NaN }
+ $Data += "`n$($_.Name) ($($_.Algorithm -join " & "))"
+ ForEach ($Algorithm in $_.Algorithm) {
+ Remove-Stat -Name "$($_.Name)_$($Algorithm)_Hashrate"
+ $_.Disabled = $false
+ }
+ # Also clear power usage
+ Remove-Stat -Name "$($_.Name)$(If ($_.Algorithm.Count -eq 1) { "_$($_.Algorithm)" })_PowerUsage"
+ $_.PowerUsage = $_.PowerCost = $_.Profit = $_.Profit_Bias = $_.Earning = $_.Earning_Bias = [Double]::NaN
+
+ $_.Reason = @($_.Reason | Where-Object { $_ -ne "Disabled by user" })
+ $_.Reason = @($_.Reason | Where-Object { $_ -ne "0 H/s Stat file" })
+ If (-not $_.Reason) { $_.Available = $true }
+
+ If ($_.Status -eq "Running") { $Variables.EndLoopTime = (Get-Date).ToUniversalTime() } # End loop immediately
+ }
+ Write-Message -Level Verbose "Web GUI: Re-benchmark triggered for $($Miners.Count) $(If ($Miners.Count -eq 1) { "miner" } Else { "miners" })."
+ $Data += "`n`n$(If ($Miners.Count -eq 1) { "The miner" } Else { "$($Miners.Count) miners" }) will re-benchmark."
+ }
+ Else {
+ $Data = "`nNo matching hashrate stats found."
+ }
+ Break
+ }
+ ElseIf ($Parameters.Miners -and $Parameters.Type -eq "PowerUsage") {
+ If ($Miners = @(Compare-Object -PassThru -IncludeEqual -ExcludeDifferent @($Variables.Miners | Select-Object) @($Parameters.Miners | ConvertFrom-Json -ErrorAction SilentlyContinue | Select-Object) -Property Name, Algorithm)) {
+ $Miners | Sort-Object Name, Algorithm | ForEach-Object {
+ If ($_.Earning -eq 0) { $_.Available = $true }
+ If ($Variables.CalculatePowerCost) {
+ $_.MeasurePowerUsage = $true
+ $_.Activated = 0 # To allow 3 attempts
+ }
+ $Stat_Name = "$($_.Name)$(If ($_.Algorithm.Count -eq 1) { "_$($_.Algorithm)" })"
+ $Data += "`n$Stat_Name"
+ Remove-Stat -Name "$($Stat_Name)_PowerUsage"
+ $_.PowerUsage = $_.PowerCost = $_.Profit = $_.Profit_Bias = $_.Earning = $_.Earning_Bias = [Double]::NaN
+
+ If ($_.Status -eq "Running") { $Variables.EndLoopTime = (Get-Date).ToUniversalTime() } # End loop immediately
+ }
+ Write-Message -Level Verbose "Web GUI: Re-measure power usage triggered for $($Miners.Count) $(If ($Miners.Count -eq 1) { "miner" } Else { "miners" })." -Verbose
+ $Data += "`n`n$(If ($Miners.Count -eq 1) { "The miner" } Else { "$($Miners.Count) miners" }) will re-measure power usage."
+ }
+ Else {
+ $Data = "`nNo matching power usage stats found."
+ }
+ Break
+ }
+ If ($Parameters.Value) { $TempStats = @($Stats.Keys | Where-Object { $_ -like "*$($Parameters.Type)" } | Where-Object { $Stats.$_.Live -eq $Parameters.Value } | ForEach-Object { $Stats.$_ }) }
+ Else { $TempStats = @($Stats.Keys | Where-Object { $_ -like "*$($Parameters.Type)" } | ForEach-Object { $Stats.$_ }) }
+ If ($TempStats) {
+ $TempStats | Sort-Object Name | ForEach-Object {
+ Remove-Stat -Name $_.Name
+ $Data += "`n$($_.Name -replace "_$($Parameters.Type)")"
+ }
+ Write-Message "Web GUI: Removed $($TempStats.Count) $($Parameters.Type) stat file$(If ($TempStats.Count -ne 1) { "s" })."
+ If ($Parameters.Type -eq "Hashrate") { $Data += "`n`nReset $($TempStats.Count) stat file$(if ($TempStats.Count -ne 1) { "s" }) with $($Parameters.Value)H/s $($Parameters.Type)." }
+ ElseIf ($Parameters.Type -eq "PowerUsage") { $Data += "`n`nReset $($TempStats.Count) stat file$(if ($TempStats.Count -ne 1) { "s" }) with $($Parameters.Value)W $($Parameters.Type)." }
+ ElseIf ($Parameters.Type -eq "Profit") { $Data += "`n`nReset $($TempStats.Count) stat file$(if ($TempStats.Count -ne 1) { "s" })." }
+ }
+ Else {
+ $Data = "`nNo matching stats found."
+ }
+ Break
+ }
+ "/functions/stat/set" {
+ If ($Parameters.Miners -and $Parameters.Type -eq "HashRate" -and $null -ne $Parameters.Value) {
+ If ($Miners = @(Compare-Object -PassThru -IncludeEqual -ExcludeDifferent @($Variables.Miners | Select-Object) @($Parameters.Miners | ConvertFrom-Json -ErrorAction SilentlyContinue | Select-Object) -Property Name, Algorithm)) {
+ $Miners | Sort-Object Name, Algorithm | ForEach-Object {
+ $_.Data = @()
+ If ($Parameters.Value -le 0 -and $Parameters.Type -eq "Hashrate") { $_.Available = $false; $_.Disabled = $true }
+ $Data += "`n$($_.Name) ($($_.Algorithm -join " & "))"
+ ForEach ($Algorithm in $_.Algorithm) {
+ $Stat_Name = "$($_.Name)_$($Algorithm)_$($Parameters.Type)"
+ If ($Parameters.Value -eq 0) { # Miner failed
+ Remove-Stat -Name $Stat_Name
+ $_.Profit = $_.Profit_Bias = $_.Earning = $_.Earning_Bias = $_.Earning_Accuracy = [Double]::NaN
+ $_.Available = $false
+ $_.Disabled = $false
+ $_.Reason = @($_.Reason | Where-Object { $_ -notlike "Disabled by user" })
+ If ($_.Reason -notcontains "0 H/s Stat file" ) { $_.Reason += "0 H/s Stat file" }
+ $_.Status = [MinerStatus]::Failed
+ }
+ ElseIf ($Parameters.Value -eq -1) { # Miner disabled
+ $_.Available = $false
+ $_.Disabled = $true
+ $_.Reason = @($_.Reason | Where-Object { $_ -notlike "0 H/s Stat file" })
+ If ($_.Reason -notcontains "Disabled by user") { $_.Reason += "Disabled by user" }
+ $_.Status = [MinerStatus]::Disabled
+ }
+ Set-Stat -Name $Stat_Name -Value $Parameters.Value -FaultDetection $false | Out-Null
+ }
+ }
+ Write-Message -Level Verbose "Web GUI: Disabled $($Miners.Count) $(If ($Miners.Count -eq 1) { "miner" } Else { "miners" })." -Verbose
+ $Data += "`n`n$(If ($Miners.Count -eq 1) { "The miner is" } Else { "$($Miners.Count) miners are" }) $(If ($Parameters.Value -eq 0) { "marked as failed" } ElseIf ($Parameters.Value -eq -1) { "disabled" } Else { "set to value $($Parameters.Value)" } )."
+ }
+ Break
+ }
+ }
+ "/functions/switchinglog/clear" {
+ Get-ChildItem -Path ".\Logs\switchinglog.csv" -File | Remove-Item -Force
+ $Data = "Switching log '.\Logs\switchinglog.csv' cleared. "
+ Break
+ }
+ "/functions/variables/get" {
+ If ($Key) {
+ $Data = $Variables.($Key -replace '\\|/','.' -split '\.' | Select-Object -Last 1) | Get-SortedObject | ConvertTo-Json -Depth 10
+ }
+ Else {
+ $Data = $Variables.Keys | Sort-Object | ConvertTo-Json -Depth 1
+ }
+ Break
+ }
+ "/functions/watchdogtimers/remove" {
+ $Data = @()
+ ForEach ($WatchdogTimer in ($Parameters.Miners | ConvertFrom-Json -ErrorAction SilentlyContinue)) {
+ If ($WatchdogTimers = @($Variables.WatchdogTimers | Where-Object MinerName -EQ $WatchdogTimer.Name | Where-Object { $_.Algorithm -eq $WatchdogTimer.Algorithm -or $WatchdogTimer.Reason -eq "Miner suspended by watchdog (all algorithms)" })) {
+ # Remove Watchdog timers
+ $Variables.WatchdogTimers = @($Variables.WatchdogTimers | Where-Object { $_ -notin $WatchdogTimers })
+ $Data += "`n$($WatchdogTimer.Name) {$($WatchdogTimer.Algorithm -join '; ')}"
+
+ # Update miner
+ $Variables.Miners | Where-Object Name -EQ $WatchdogTimer.Name | Where-Object Algorithm -EQ $WatchdogTimer.Algorithm | ForEach-Object {
+ $_.Reason = @($_.Reason | Where-Object { $_ -notlike "Miner suspended by watchdog *" })
+ If (-not $_.Reason) { $_.Available = $true }
+ }
+ }
+ }
+ ForEach ($WatchdogTimer in ($Parameters.Pools | ConvertFrom-Json -ErrorAction SilentlyContinue)) {
+ If ($WatchdogTimers = @($Variables.WatchdogTimers | Where-Object PoolName -EQ $WatchdogTimer.Name | Where-Object { $_.Algorithm -EQ $WatchdogTimer.Algorithm -or $WatchdogTimer.Reason -eq "Pool suspended by watchdog" })) {
+ # Remove Watchdog timers
+ $Variables.WatchdogTimers = @($Variables.WatchdogTimers | Where-Object { $_ -notin $WatchdogTimers })
+ $Data += "`n$($WatchdogTimer.Name) {$($WatchdogTimer.Algorithm -join '; ')}"
+
+ # Update pool
+ $Variables.Pools | Where-Object Name -EQ $WatchdogTimer.Name | Where-Object Algorithm -EQ $WatchdogTimer.Algorithm | ForEach-Object {
+ $_.Reason = @($_.Reason | Where-Object { $_ -notlike "Algorithm@Pool suspended by watchdog" })
+ $_.Reason = @($_.Reason | Where-Object { $_ -notlike "Pool suspended by watchdog*" })
+ If (-not $_.Reason) { $_.Available = $true }
+ }
+ }
+ }
+ If ($WatchdogTimers) {
+ $Message = "$($Data.Count) $(If ($Data.Count -eq 1) { "watchdog timer" } Else { "watchdog timers" }) removed."
+ Write-Message -Level Verbose "Web GUI: $Message"
+ $Data += "`n`n$Message"
+ }
+ Else {
+ $Data = "`nNo matching watchdog timers found."
+ }
+ Break
+ }
+ "/functions/watchdogtimers/reset" {
+ $Variables.WatchDogTimers = @()
+ $Variables.Miners | ForEach-Object { $_.Reason = @($_.Reason | Where-Object { $_ -notlike "Miner suspended by watchdog *" }); $_ } | Where-Object { -not $_.Reason } | ForEach-Object { $_.Available = $true }
+ $Variables.Pools | ForEach-Object { $_.Reason = @($_.Reason | Where-Object { $_ -notlike "*Pool suspended by watchdog" }); $_ } | Where-Object { -not $_.Reason } | ForEach-Object { $_.Available = $true }
+ Write-Message -Level Verbose "Web GUI: All watchdog timers reset."
+ $Data = "`nWatchdog timers will be recreated in next cycle."
+ Break
+ }
+ "/algorithms" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.Algorithms | Select-Object)
+ Break
+ }
+ "/allcurrencies" {
+ $Data = ConvertTo-Json -Depth 10 ($Variables.AllCurrencies)
+ break
+ }
+ "/apiversion" {
+ $Data = ConvertTo-Json -Depth 10 @($APIVersion | Select-Object)
+ Break
+ }
+ "/balances" {
+ $Data = ConvertTo-Json -Depth 10 ($Variables.Balances | Select-Object)
+ Break
+ }
+ "/balancedata" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.BalanceData | Sort-Object DateTime -Descending)
+ Break
+ }
+ "/btc" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.Rates.BTC.($Config.Currency) | Select-Object)
+ Break
+ }
+ "/balancescurrencies" {
+ $Data = ConvertTo-Json -Depth 10 ($Variables.BalancesCurrencies)
+ break
+ }
+ "/brainjobs" {
+ $Data = ConvertTo-Json -Depth 2 @($Variables.BrainJobs | Select-Object)
+ Break
+ }
+ "/coinnames" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.CoinNames | Select-Object)
+ Break
+ }
+ "/config" {
+ $Data = ConvertTo-Json -Depth 10 (Get-Content -Path $Variables.ConfigFile | ConvertFrom-Json -Depth 10 | Get-SortedObject)
+ If (-not ($Data | ConvertFrom-Json).ConfigFileVersion) {
+ $Data = ConvertTo-Json -Depth 10 ($Config | Select-Object -Property * -ExcludeProperty PoolsConfig)
+ }
+ Break
+ }
+ "/configfile" {
+ $Data = ConvertTo-Json -Depth 10 ($Variables.ConfigFile)
+ break
+ }
+ "/configrunning" {
+ $Data = ConvertTo-Json -Depth 10 ($Config | Get-SortedObject)
+ Break
+ }
+ "/currency" {
+ $Data = ConvertTo-Json -Depth 10 @($Config.Currency)
+ Break
+ }
+ "/dagdata" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.DAGdata | Select-Object)
+ Break
+ }
+ "/dagdata2" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.DAGdata.Currency | Select-Object)
+ Break
+ }
+ "/devices" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.Devices | Sort-Object Name | Select-Object)
+ Break
+ }
+ "/devices/enabled" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.Devices | Where-Object State -EQ "Enabled" | Select-Object)
+ Break
+ }
+ "/devices/disabled" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.Devices | Where-Object State -EQ "Disabled" | Select-Object)
+ Break
+ }
+ "/devices/unsupported" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.Devices | Where-Object State -EQ "Unsupported" | Select-Object)
+ Break
+ }
+ "/defaultalgorithm" {
+ $Data = ConvertTo-Json -Depth 10 (Get-DefaultAlgorithm)
+ Break
+ }
+ "/displayworkers" {
+ If ($Config.MonitoringServer -and $Config.MonitoringUser -and $Config.ShowWorkerStatus) {
+ Receive-MonitoringData
+ $DisplayWorkers = [System.Collections.ArrayList]@(
+ $Variables.Workers | Select-Object @(
+ @{ Name = "Worker"; Expression = { $_.worker } },
+ @{ Name = "Status"; Expression = { $_.status } },
+ @{ Name = "LastSeen"; Expression = { "$($_.date)" } },
+ @{ Name = "Version"; Expression = { $_.version } },
+ @{ Name = "EstimatedEarning"; Expression = { [Decimal](($_.Data.Earning | Measure-Object -Sum).Sum) * $Variables.Rates.BTC.($_.Data.Currency | Select-Object -Unique) } },
+ @{ Name = "EstimatedProfit"; Expression = { [Decimal](($_.Data.Profit | Measure-Object -Sum).Sum) * $Variables.Rates.BTC.($_.Data.Currency | Select-Object -Unique) } },
+ @{ Name = "Currency"; Expression = { $_.Data.Currency | Select-Object -Unique } },
+ @{ Name = "Miner"; Expression = { $_.data.name -join ' '} },
+ @{ Name = "Pool"; Expression = { ($_.data | ForEach-Object { ($_.Pool -split "," | ForEach-Object { $_ -replace "Internal$", " (Internal)" -replace "External", " (External)" }) -join " & "}) -join " " } },
+ @{ Name = "Algorithm"; Expression = { ($_.data | ForEach-Object { $_.Algorithm -split "," -join " & " }) -join " " } },
+ @{ Name = "Live Hashrate"; Expression = { If ($_.data.CurrentSpeed) { ($_.data | ForEach-Object { ($_.CurrentSpeed | ForEach-Object { "$($_ | ConvertTo-Hash)/s" -replace "\s+", " " }) -join " & " }) -join " " } Else { "" } } },
+ @{ Name = "Benchmark Hashrate"; Expression = { If ($_.data.EstimatedSpeed) { ($_.data | ForEach-Object { ($_.EstimatedSpeed | ForEach-Object { "$($_ | ConvertTo-Hash)/s" -replace "\s+", " " }) -join " & " }) -join " " } Else { "" } } }
+ ) | Sort-Object "Worker Name"
+ )
+ $Data = ConvertTo-Json @($DisplayWorkers | Select-Object)
+ }
+ Else {
+ $Data = $null
+ }
+ Break
+ }
+ "/driverversion" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.DriverVersion | Select-Object)
+ Break
+ }
+ "/earningschartdata" {
+ $Data = $Variables.EarningsChartData | ConvertTo-Json
+ Break
+ }
+ "/earningschartdata24hr" {
+ $Data = $Variables.EarningsChartData24hr | ConvertTo-Json
+ Break
+ }
+ "/extracurrencies" {
+ $Data = ConvertTo-Json -Depth 10 ($Config.ExtraCurrencies)
+ break
+ }
+ "/miners" {
+ $Data = ConvertTo-Json -Depth 4 @($Variables.Miners | Select-Object -Property * -ExcludeProperty Data, DataReaderJob, Devices, Process, intervals | ForEach-Object { If ($_.WorkersRunning) { $_ | Add-Member Workers $_.WorkersRunning -Force }; $_ } | Select-Object -Property * -ExcludeProperty WorkersRunning | Sort-Object Status, DeviceName, Name)
+ Break
+ }
+ "/miners/available" {
+ $Data = ConvertTo-Json -Depth 4 @($Variables.Miners | Where-Object Available -EQ $true | Select-Object -Property * -ExcludeProperty Data, DataReaderJob, Devices, Process)
+ Break
+ }
+ "/miners/best" {
+ $Data = ConvertTo-Json -Depth 4 @($Variables.BestMiners | Select-Object -Property * -ExcludeProperty Data, DataReaderJob, Devices, Process | ConvertTo-Json -Depth 4 | ConvertFrom-Json | ForEach-Object { If ($_.WorkersRunning) { $_ | Add-Member Workers $_.WorkersRunning -Force }; $_ } | Select-Object -Property * -ExcludeProperty WorkersRunning | Sort-Object Status, DeviceName, @{Expression = "Earning_Bias"; Descending = $True })
+ Break
+ }
+ "/miners/bestminers_combo" {
+ $Data = ConvertTo-Json -Depth 4 @($Variables.BestMiners_Combo | Select-Object -Property * -ExcludeProperty Data, DataReaderJob, Devices, Process)
+ Break
+ }
+ "/miners/bestminers_combos" {
+ $Data = ConvertTo-Json -Depth 4 @($Variables.BestMiners_Combos | Select-Object -Property * -ExcludeProperty Data, DataReaderJob, Devices, Process)
+ Break
+ }
+ "/miners/disabled" {
+ $Data = ConvertTo-Json -Depth 4 @($Variables.Miners | Where-Object { $_.Status -EQ [MinerStatus]::Disabled } | Select-Object -Property * -ExcludeProperty Data, DataReaderJob, Devices, Process | Sort-Object DeviceName, EndTime)
+ Break
+ }
+ "/miners/failed" {
+ $Data = ConvertTo-Json -Depth 4 @($Variables.Miners | Where-Object { $_.Status -EQ [MinerStatus]::Failed } | Select-Object -Property * -ExcludeProperty Data, DataReaderJob, Devices, Process | Sort-Object DeviceName, EndTime)
+ Break
+ }
+ "/miners/mostprofitable" {
+ $Data = ConvertTo-Json -Depth 4 @($Variables.MostProfitableMiners | Select-Object -Property * -ExcludeProperty Data, DataReaderJob, Devices, Process | Sort-Object Status, DeviceName, @{Expression = "Earning_Bias"; Descending = $True })
+ Break
+ }
+ "/miners/running" {
+ $Data = ConvertTo-Json -Depth 4 @($Variables.Miners | Where-Object Available -EQ $true | Where-Object { $_.Status -EQ [MinerStatus]::Running } | Select-Object -Property * -ExcludeProperty Data, DataReaderJob, Devices, Process, Workers | ConvertTo-Json -Depth 4 | ConvertFrom-Json | ForEach-Object { $_ | Add-Member Workers $_.WorkersRunning; $_ } | Select-Object -Property * -ExcludeProperty WorkersRunning)
+ Break
+ }
+ "/miners/unavailable" {
+ $Data = ConvertTo-Json -Depth 4 @($Variables.Miners | Where-Object Available -NE $true | Select-Object -Property * -ExcludeProperty Data, DataReaderJob, Devices, Process)
+ Break
+ }
+ "/miners_device_combos" {
+ $Data = ConvertTo-Json -Depth 4 @($Variables.Miners_Device_Combos | Select-Object -Property * -ExcludeProperty Data, DataReaderJob, Devices, Process)
+ Break
+ }
+ "/miningpowercost" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.MiningPowerCost | Select-Object)
+ Break
+ }
+ "/miningearning" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.MiningEarning | Select-Object)
+ Break
+ }
+ "/miningprofit" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.MiningProfit | Select-Object)
+ Break
+ }
+ "/newminers" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.NewMiners | Select-Object)
+ Break
+ }
+ "/newpools" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.NewPools | Select-Object)
+ Break
+ }
+ "/poolsconfig" {
+ $Data = ConvertTo-Json -Depth 10 @($Config.PoolsConfig | Select-Object)
+ Break
+ }
+ "/poolsconfigfile" {
+ $Data = ConvertTo-Json -Depth 10 ($Variables.PoolsConfigFile)
+ Break
+ }
+ "/pooldata" {
+ $Data = ConvertTo-Json -Depth 10 ($Variables.PoolData)
+ break
+ }
+ "/pooldata" {
+ $Data = ConvertTo-Json -Depth 10 ($Variables.PoolData)
+ break
+ }
+ "/poolnames" {
+ $Data = ConvertTo-Json -Depth 10 ($Variables.PoolNames)
+ break
+ }
+ "/pools" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.Pools | Select-Object | Sort-Object Name, Algorithm)
+ Break
+ }
+ "/pools/added" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.AddedPools | Select-Object | Sort-Object Name, Algorithm)
+ Break
+ }
+ "/pools/available" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.Pools | Where-Object Available -EQ $true | Select-Object | Sort-Object Name, Algorithm)
+ Break
+ }
+ "/pools/best" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.Pools | Where-Object Best -EQ $true | Select-Object | Sort-Object Best, Name, Algorithm)
+ Break
+ }
+ "/pools/new" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.NewPools | Select-Object | Sort-Object Name, Algorithm)
+ Break
+ }
+ "/pools/lastearnings" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.PoolsLastEarnings)
+ Break
+ }
+ "/pools/lastused" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.PoolsLastUsed)
+ Break
+ }
+ "/pools/unavailable" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.Pools | Where-Object Available -NE $true | Select-Object | Sort-Object Name, Algorithm)
+ Break
+ }
+ "/pools/updated" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.UpdatedPools | Select-Object | Sort-Object Name, Algorithm)
+ Break
+ }
+ "/poolreasons" {
+ $Data = ConvertTo-Json -Depth 10 @(($Variables.Pools | Where-Object Available -NE $true).Reason | Sort-Object -Unique)
+ Break
+ }
+ "/poolvariants" {
+ $Data = ConvertTo-Json -Depth 10 ($Variables.PoolVariants)
+ break
+ }
+ "/rates" {
+ $Data = ConvertTo-Json -Depth 10 ($Variables.Rates | Select-Object)
+ Break
+ }
+ "/regions" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.Regions.PSObject.Properties.Value | Sort-Object -Unique)
+ Break
+ }
+ "/regionsdata" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.Regions)
+ Break
+ }
+ "/stats" {
+ $Data = ConvertTo-Json -Depth 10 @($Stats | Select-Object)
+ Break
+ }
+ "/summary" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.Summary | Select-Object)
+ Break
+ }
+ "/switchinglog" {
+ $Data = ConvertTo-Json -Depth 10 @(Get-Content ".\Logs\switchinglog.csv" | ConvertFrom-Csv | Select-Object -Last 1000)
+ Break
+ }
+ "/unprofitablealgorithms" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.UnprofitableAlgorithms | Select-Object)
+ Break
+ }
+ "/watchdogtimers" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.WatchdogTimers | Select-Object)
+ Break
+ }
+ "/wallets" {
+ $Data = ConvertTo-Json -Depth 10 @($Config.Wallets | Select-Object)
+ Break
+ }
+ "/watchdogexpiration" {
+ $Data = ConvertTo-Json -Depth 10 @($Variables.WatchdogReset)
+ Break
+ }
+ "/version" {
+ $Data = @("$($Variables.Branding.ProductLabel) Version: $($Variables.Branding.Version)", "API Version: $($Variables.APIVersion)", "PWSH Version: $($PSVersionTable.PSVersion.ToString())") | ConvertTo-Json
+ Break
+ }
+ Default {
+ # Set index page
+ If ($Path -eq "/") { $Path = "/index.html" }
+
+ # Check if there is a file with the requested path
+ $Filename = "$BasePath$Path"
+ If (Test-Path $Filename -PathType Leaf -ErrorAction SilentlyContinue) {
+ # If the file is a PowerShell script, execute it and return the output. A $Parameters parameter is sent built from the query string
+ # Otherwise, just return the contents of the file
+ $File = Get-ChildItem $Filename -File
+
+ If ($File.Extension -eq ".ps1") {
+ $Data = & $File.FullName -Parameters $Parameters
+ }
+ Else {
+ $Data = Get-Content $Filename -Raw
+
+ # Process server side includes for html files
+ # Includes are in the traditional '' format used by many web servers
+ If ($File.Extension -eq ".html") {
+ $IncludeRegex = [regex]''
+ $IncludeRegex.Matches($Data) | Foreach-Object {
+ $IncludeFile = $BasePath + '/' + $_.Groups[1].Value
+ If (Test-Path $IncludeFile -PathType Leaf) {
+ $IncludeData = Get-Content $IncludeFile -Raw
+ $Data = $Data -replace $_.Value, $IncludeData
+ }
+ }
+ }
+ }
+
+ # Set content type based on file extension
+ If ($MIMETypes.ContainsKey($File.Extension)) {
+ $ContentType = $MIMETypes[$File.Extension]
+ }
+ Else {
+ # If it's an unrecognized file type, prompt for download
+ $ContentType = "application/octet-stream"
+ }
+ }
+ Else {
+ $StatusCode = 404
+ $ContentType = "text/html"
+ $Data = "URI '$Path' is not a valid resource."
+ }
+ }
+ }
+
+ # If $Data is null, the API will just return whatever data was in the previous request. Instead, show an error
+ # This happens if the script just started and hasn't filled all the properties in yet.
+ If ($null -eq $Data) {
+ $Data = @{ "Error" = "API data not available" } | ConvertTo-Json
+ }
+
+ # Send the response
+ $Response.Headers.Add("Content-Type", $ContentType)
+ $Response.StatusCode = $StatusCode
+ $ResponseBuffer = [System.Text.Encoding]::UTF8.GetBytes($Data)
+ $Response.ContentLength64 = $ResponseBuffer.Length
+ $Response.OutputStream.Write($ResponseBuffer, 0, $ResponseBuffer.Length)
+ $Response.Close()
+
+ Remove-Variable AlgorithmList, BalanceDataEntries, ContentType, Data, DisabledPoolsCount, EnabledPoolsCount, File, DisplayWorkers, IncludeData, IncludeFile, IncludeRegex, Key, Lines, Message, MinerNames, Miners, Path, PoolConfig, PoolBaseName, PoolName, Pools, Reason, ResponseBuffer, Stat_Name, StatusCode, TempStats, Value, Values, WatchdogTimer, WatchdogTimers -ErrorAction SilentlyContinue
+ }
+ # Only gets here if something is wrong and the server couldn't start or stops listening
+ $Server.Stop()
+ $Server.Close()
+ }
+ ) # End of $APIServer
+ $AsyncObject = $PowerShell.BeginInvoke()
+
+ $Variables.APIRunspace | Add-Member -Force @{
+ PowerShell = $PowerShell
+ AsyncObject = $AsyncObject
+ }
+}
+
+Function Stop-APIServer {
+ If ($Variables.APIRunspace) {
+ If ($Variables.APIRunspace.APIServer) {
+ If ($Variables.APIRunspace.APIServer.IsListening) { $Variables.APIRunspace.APIServer.Stop() }
+ $Variables.APIRunspace.APIServer.Close()
+ }
+ $Variables.APIRunspace.APIPort = $null
+ $Variables.APIRunspace.Close()
+ If ($Variables.APIRunspace.PowerShell) { $Variables.APIRunspace.PowerShell.Dispose() }
+ $Variables.Remove("APIRunspace")
+ }
+}
diff --git a/Includes/BalancesTracker.ps1 b/Includes/BalancesTracker.ps1
new file mode 100644
index 0000000000..78449ed4ea
--- /dev/null
+++ b/Includes/BalancesTracker.ps1
@@ -0,0 +1,386 @@
+using module .\Include.psm1
+
+<#
+Copyright (c) 2018 Nemos, MrPlus & UselessGuru
+BalancesTrackerJob.ps1 Written by MrPlusGH https://github.com/MrPlusGH & UseLessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: BalancesTracker.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+# Start transcript log
+If ($Config.Transcript) { Start-Transcript -Path ".\Logs\$((Get-Item $MyInvocation.MyCommand.Path).BaseName)-Transcript_-$(Get-Date -Format "yyyy-MM-dd").log" -Append -Force | Out-Null }
+
+(Get-Process -Id $PID).PriorityClass = "BelowNormal"
+
+$Balances = [Ordered]@{ }
+$BalanceObjects = @()
+$AllBalanceObjects = @()
+$Earnings = @()
+
+# Get pools last earnings
+$Variables.PoolsLastEarnings = If (Test-Path -Path ".\Data\PoolsLastEarnings.json" -PathType Leaf) { Get-Content ".\Data\PoolsLastEarnings.json" | ConvertFrom-Json | Get-SortedObject } Else { [Ordered]@{ } }
+
+# Get pools data
+$PoolData = If (Test-Path -Path ".\Data\PoolData.json" -PathType Leaf) { Get-Content ".\Data\PoolData.json" | ConvertFrom-Json } Else { [PSCustomObject]@{ } }
+
+# Read existing earning data, use data from last file
+ForEach ($Filename in (Get-ChildItem ".\Data\BalancesTrackerData*.json" | Sort-Object -Descending)) {
+ $AllBalanceObjects = (Get-Content $Filename | ConvertFrom-Json) | Where-Object Balance -NE $null
+ If ($AllBalanceObjects.Count -gt ($PoolData.Count / 2)) {
+ $Variables.BalanceData = $AllBalanceObjects
+ Break
+ }
+}
+If ($AllBalanceObjects -isnot [Array]) { $AllBalanceObjects = @() }
+Else { $AllBalanceObjects | ForEach-Object { $_.DateTime = [DateTime]$_.DateTime } }
+
+# Read existing earning data, use data from last file
+ForEach($Filename in (Get-ChildItem ".\Data\DailyEarnings*.csv" | Sort-Object -Descending)) {
+ $Earnings = @(Import-Csv $FileName -ErrorAction SilentlyContinue)
+ If ($Earnings.Count -gt $PoolData.Count / 2) { Break }
+}
+Remove-Variable FileName -ErrorAction Ignore
+
+While ($true) {
+
+ If ($Config.BalancesTrackerPollInterval -gt 0) {
+
+ If ($Now.Date -ne (Get-Date).Date) {
+ # Keep a copy on start & at date change
+ If (Test-Path -Path ".\Data\BalancesTrackerData.json" -PathType Leaf) { Copy-Item -Path ".\Data\BalancesTrackerData.json" -Destination ".\Data\BalancesTrackerData_$(Get-Date -Format "yyyy-MM-dd_HH-mm-ss").json" }
+ If (Test-Path -Path ".\Data\DailyEarnings.csv" -PathType Leaf) { Copy-Item -Path ".\Data\DailyEarnings.csv" -Destination ".\Data\DailyEarnings_$(Get-Date -Format "yyyy-MM-dd_HH-mm-ss").csv" }
+ # Keep only the last 3 logs
+ Get-ChildItem ".\Data\BalancesTrackerData_*.json" | Sort-Object | Select-Object -Skiplast 3 | Remove-Item -Force -Recurse
+ Get-ChildItem ".\Data\DailyEarnings_*.csv" | Sort-Object | Select-Object -Skiplast 3 | Remove-Item -Force -Recurse
+ }
+
+ $Now = (Get-Date).ToUniversalTime()
+
+ # Get pools to track
+ $PoolsToTrack = @(Get-PoolBaseName (Get-ChildItem ".\Balances\*.ps1" -File).BaseName) | Sort-Object -Unique | Where-Object { $_ -notin $Config.BalancesTrackerIgnorePool }
+
+ # Fetch balances data from pools
+ $BalanceObjects = @($BalanceObjects | Where-Object { $_.Pool -ne "ProHashing" -or $_.DateTime -gt $Now.AddHours((Get-TimeZone -ID "Eastern Standard Time").BaseUtcOffset.totalhours).Date }) # ProHashing does not send balance if all is paid -> remove from balances
+ If ($PoolsToTrack) { Write-Message "Balances Tracker is requesting data from pool$(If ($PoolsToTrack.Count -gt 1) { "s" }) '$($PoolsToTrack -join ', ')'..." }
+ $PoolsToTrack | ForEach-Object { $BalanceObjects += @(& ".\Balances\$($_).ps1") }
+
+ # Keep most recent balance objects, keep empty balances for 7 days
+ $BalanceObjects = @(@($BalanceObjects + $AllBalanceObjects) | Where-Object Pool -notin @($Config.BalancesTrackerIgnorePool) | Where-Object { $_.Unpaid -gt 0 -or (($_.Pending -gt 0 -or $_.Balance -gt 0) -and $_.DateTime -gt $Now.AddDays(-7)) } | Where-Object { $_.Wallet } | Group-Object Pool, Currency, Wallet | ForEach-Object { $_.Group | Sort-Object DateTime | Select-Object -Last 1 })
+
+ # Fix for pool reporting incorrect currency, e.g ZergPool ZER instead of BTC
+ $BalanceObjects = @($BalanceObjects | Where-Object { $_.Pool -match "^MiningPoolHub(|Coins)$|^ProHashing(|24h)$" }) + @($BalanceObjects | Where-Object { $_.Pool -notmatch "^MiningPoolHub(|Coins)$|^ProHashing(|24h)$" } | Group-Object Pool, Wallet | ForEach-Object { $_.Group | Sort-Object DateTime | Select-Object -Last 1 })
+
+ # Read exchange rates
+ Get-Rate
+
+ $BalanceObjects | Where-Object { $_.DateTime -gt $Now } | ForEach-Object {
+ $PoolBalanceObject = $_
+
+ $PoolBalanceObjects = @($AllBalanceObjects | Where-Object Pool -EQ $PoolBalanceObject.Pool | Where-Object Currency -EQ $PoolBalanceObject.Currency | Where-Object Wallet -EQ $PoolBalanceObject.Wallet | Sort-Object DateTime)
+
+ # Get threshold currency and value
+ $PayoutThresholdCurrency = $PoolBalanceObject.Currency
+ $PayoutThreshold = $PoolBalanceObject.PayoutThreshold
+
+ If (-not $PayoutThreshold) { $PayoutThreshold = [Double]($Config.PoolsConfig.($PoolBalanceObject.Pool -replace " External$| Internal$").Variant.($PoolBalanceObject.Pool).PayoutThreshold.$PayoutThresholdCurrency) }
+ If (-not $PayoutThreshold) { $PayoutThreshold = [Double]($Config.PoolsConfig.($PoolBalanceObject.Pool -replace " External$| Internal$").PayoutThreshold.$PayoutThresholdCurrency) }
+ If (-not $PayoutThreshold) { $PayoutThreshold = [Double]($Config.PoolsConfig.($PoolBalanceObject.Pool).PayoutThreshold.$PayoutThresholdCurrency) }
+
+ If (-not $PayoutThreshold -and $PoolBalanceObject.Currency -eq "BTC") {
+ $PayoutThresholdCurrency = "mBTC"
+ If (-not $PayoutThreshold) { $PayoutThreshold = [Double]($Config.PoolsConfig.($PoolBalanceObject.Pool -replace " External$| Internal$").Variant.($PoolBalanceObject.Pool).PayoutThreshold.$PayoutThresholdCurrency) }
+ If (-not $PayoutThreshold) { $PayoutThreshold = [Double]($Config.PoolsConfig.($PoolBalanceObject.Pool -replace " External$| Internal$").PayoutThreshold.$PayoutThresholdCurrency) }
+ If (-not $PayoutThreshold) { $PayoutThreshold = [Double]($Config.PoolsConfig.($PoolBalanceObject.Pool).PayoutThreshold.$PayoutThresholdCurrency) }
+ }
+
+ If (-not $PayoutThreshold) {
+ $PayoutThreshold = If ($Config.PoolsConfig.($PoolBalanceObject.Pool).PayoutThreshold."*" -like "* *") { [Double](($Config.PoolsConfig.($PoolBalanceObject.Pool).PayoutThreshold."*" -split ' ' | Select-Object -First 1) * $Variables.Rates.$PayoutThresholdCurrency.($Config.PoolsConfig.($PoolBalanceObject.Pool).PayoutThreshold."*" -split ' ' | Select-Object -Index 1)) } Else { [Double]($PoolConfig.PayoutThreshold."*") }
+ }
+
+ If ($PayoutThresholdCurrency -eq "BTC" -and $Config.UsemBTC -eq $true) {
+ $PayoutThresholdCurrency = "mBTC"
+ $PayoutThreshold *= 1000
+ }
+
+ $Growth1 = $Growth6 = $Growth24 = $Growth168 = $Growth720 = $GrowthToday = $AvgHourlyGrowth = $AvgDailyGrowth = $AvgWeeklyGrowth = $Delta = $Payout = $HiddenPending = [Double]0
+
+ If ($PoolBalanceObjects.Count -eq 0) {
+ $PoolBalanceObject | Add-Member Earnings ([Double]($PoolBalanceObject.Unpaid))
+ $PoolBalanceObject | Add-Member Payout ([Double](0))
+ $PoolBalanceObject | Add-Member Total ([Double]($PoolBalanceObject.Unpaid))
+ $PoolBalanceObject | Add-Member Delta ([Double]0)
+
+ $PoolBalanceObjects += $PoolBalanceObject
+ $AllBalanceObjects += $PoolBalanceObject
+
+ $AvgHourlyGrowth = $AvgDailyGrowth = $AvgWeeklyGrowth = 0
+ }
+ Else {
+ If ($PoolBalanceObject.Pool -like "NiceHash*") {
+ If ($PoolBalanceObject.Withdrawal -gt 0) {
+ # NiceHash temporarily reduces 'Balance' value before paying out
+ $PoolBalanceObject.Balance += $PoolBalanceObject.Withdrawal
+ $Payout = 0
+ }
+ ElseIf (($PoolBalanceObjects | Select-Object -Last 1).Withdrawal -gt 0 -and $PoolBalanceObject.Withdrawal -eq 0) {
+ # Payout occurred
+ $Payout = ($PoolBalanceObjects | Select-Object -Last 1).Withdrawal
+ }
+ ElseIf ($PoolBalanceObject.Withdrawal -eq 0) {
+ # NiceHash temporarily hides some 'pending' value while processing payouts
+ If ($PoolBalanceObject.Pending -lt ($PoolBalanceObjects | Select-Object -Last 1).Pending) {
+ $HiddenPending = ($PoolBalanceObjects | Select-Object -Last 1).Pending - $PoolBalanceObject.Pending
+ $PoolBalanceObject | Add-Member HiddenPending ([Double]$HiddenPending)
+ }
+ # When payouts are processed the hidden pending value gets added to the balance
+ If (($PoolBalanceObjects | Select-Object -Last 1).HiddenPending -gt 0) {
+ If ($PoolBalanceObject.Balance -eq (($PoolBalanceObjects | Select-Object -Last 1).Balance)) {
+ # Payout processing complete
+ $HiddenPending *= -1
+ }
+ Else {
+ # Still processing payouts
+ $HiddenPending = ($PoolBalanceObjects | Select-Object -Last 1).HiddenPending
+ $PoolBalanceObject | Add-Member HiddenPending ([Double]$HiddenPending)
+ }
+ }
+ If (($PoolBalanceObjects | Select-Object -Last 1).Unpaid -gt $PoolBalanceObject.Unpaid) {
+ $Payout = ($PoolBalanceObjects | Select-Object -Last 1).Unpaid - $PoolBalanceObject.Unpaid
+ }
+ Else {
+ $Payout = 0
+ }
+ }
+ $Delta = $PoolBalanceObject.Unpaid - ($PoolBalanceObjects | Select-Object -Last 1).Unpaid
+ $PoolBalanceObject | Add-Member Earnings ([Double]($PoolBalanceObjects | Select-Object -Last 1).Earnings + $Delta + $HiddenPending + $Payout)
+ }
+ ElseIf ($PoolBalanceObject.Pool -match "^MiningPoolHub(|Coins)$") {
+ # MiningHubPool never reduces earnings
+ $Delta = $PoolBalanceObject.Unpaid - ($PoolBalanceObjects | Select-Object -Last 1).Unpaid
+ If ($Delta -lt 0) {
+ # Payout occured
+ $Payout = $Delta * -1
+ $PoolBalanceObject | Add-Member Earnings ([Double]($PoolBalanceObjects | Select-Object -Last 1).Earnings)
+ }
+ Else {
+ $Payout = 0
+ $PoolBalanceObject | Add-Member Earnings ([Double]($PoolBalanceObjects | Select-Object -Last 1).Earnings + $Delta)
+ }
+ }
+ ElseIf ($PoolBalanceObject.Pool -match "^ProHashing.*") {
+ # ProHashing never reduces earnings
+ $Delta = $PoolBalanceObject.Balance - ($PoolBalanceObjects | Select-Object -Last 1).Balance
+ If ($PoolBalanceObject.Unpaid -lt ($PoolBalanceObjects | Select-Object -Last 1).Unpaid) {
+ # Payout occured
+ $Payout = ($PoolBalanceObjects | Select-Object -Last 1).Unpaid - $PoolBalanceObject.Unpaid
+ $PoolBalanceObject | Add-Member Earnings ([Double]($PoolBalanceObjects | Select-Object -Last 1).Earnings + $PoolBalanceObject.Unpaid)
+ }
+ Else {
+ $Payout = 0
+ $PoolBalanceObject | Add-Member Earnings ([Double]($PoolBalanceObjects | Select-Object -Last 1).Earnings + $Delta)
+ }
+ }
+ Else {
+ # BlockMasters, BlazePool, HiveON, NLPool, ZergPool, ZPool
+ $Delta = $PoolBalanceObject.Unpaid - ($PoolBalanceObjects | Select-Object -Last 1).Unpaid
+ # Current 'Unpaid' is smaller
+ If ($Delta -lt 0) {
+ If (($Delta * -1) -gt $(If ($PayoutThresholdCurrency -eq "mBTC") { $PayoutThreshold / 1000 } Else { $PayoutThreshold }) * 0.5) {
+ # Payout occured (delta > 50% of payout limit)
+ $Payout = $Delta * -1
+ }
+ Else {
+ # Pool reduced earnings
+ $Payout = $Delta = 0
+ }
+ $PoolBalanceObject | Add-Member Earnings ([Double]($PoolBalanceObjects | Select-Object -Last 1).Earnings)
+ }
+ Else {
+ $Payout = 0
+ $PoolBalanceObject | Add-Member Earnings ([Double]($PoolBalanceObjects | Select-Object -Last 1).Earnings + $Delta)
+ }
+ }
+ $PoolBalanceObject | Add-Member Payout ([Double]$Payout)
+ $PoolBalanceObject | Add-Member Paid ([Double](($PoolBalanceObjects.Paid | Measure-Object -Maximum).Maximum + $Payout)) -Force
+ $PoolBalanceObject | Add-Member Delta ([Double]$Delta)
+
+ If ((($Now - $PoolBalanceObjects[0].DateTime).TotalHours) -lt 1) {
+ # Only calculate if current balance data
+ If ($PoolBalanceObject.DateTime -gt $Now.AddMinutes(-1)) {
+ $Growth1 = $Growth6 = $Growth24 = $Growth168 = $Growth720 = [Double]($PoolBalanceObject.Earnings - $PoolBalanceObjects[0].Earnings)
+ }
+ }
+ Else {
+ # Only calculate if current balance data
+ If ($PoolBalanceObjects | Where-Object { $_.DateTime -ge $Now.AddHours(-1) }) { $Growth1 = [Double]($PoolBalanceObject.Earnings - ($PoolBalanceObjects | Where-Object { $_.DateTime -ge $Now.AddHours(-1) } | Sort-Object Date | Select-Object -First 1).Earnings) }
+ If ($PoolBalanceObjects | Where-Object { $_.DateTime -ge $Now.AddHours(-6) }) { $Growth6 = [Double]($PoolBalanceObject.Earnings - ($PoolBalanceObjects | Where-Object { $_.DateTime -ge $Now.AddHours(-6) } | Sort-Object Date | Select-Object -First 1).Earnings) }
+ If ($PoolBalanceObjects | Where-Object { $_.DateTime -ge $Now.AddHours(-24) }) { $Growth24 = [Double]($PoolBalanceObject.Earnings - ($PoolBalanceObjects | Where-Object { $_.DateTime -ge $Now.AddHours(-24) } | Sort-Object Date | Select-Object -First 1).Earnings) }
+ If ($PoolBalanceObjects | Where-Object { $_.DateTime -ge $Now.AddHours(-168) }) { $Growth168 = [Double]($PoolBalanceObject.Earnings - ($PoolBalanceObjects | Where-Object { $_.DateTime -ge $Now.AddHours(-168) } | Sort-Object Date | Select-Object -First 1).Earnings) }
+ If ($PoolBalanceObjects | Where-Object { $_.DateTime -ge $Now.AddHours(-720) }) { $Growth720 = [Double]($PoolBalanceObject.Earnings - ($PoolBalanceObjects | Where-Object { $_.DateTime -ge $Now.AddHours(-720) } | Sort-Object Date | Select-Object -First 1).Earnings) }
+ }
+
+
+ $AvgHourlyGrowth = If ($PoolBalanceObjects | Where-Object { $_.DateTime -lt $Now.AddHours(-1) }) { [Double](($PoolBalanceObject.Earnings - $PoolBalanceObjects[0].Earnings) / ($Now - $PoolBalanceObjects[0].DateTime).TotalHours) } Else { $Growth1 }
+ $AvgDailyGrowth = If ($PoolBalanceObjects | Where-Object { $_.DateTime -lt $Now.AddDays(-1) }) { [Double](($PoolBalanceObject.Earnings - $PoolBalanceObjects[0].Earnings) / ($Now - $PoolBalanceObjects[0].DateTime).TotalDays) } Else { $Growth24 }
+ $AvgWeeklyGrowth = If ($PoolBalanceObjects | Where-Object { $_.DateTime -lt $Now.AddDays(-7) } ) { [Double](($PoolBalanceObject.Earnings - $PoolBalanceObjects[0].Earnings) / ($Now - $PoolBalanceObjects[0].DateTime).TotalDays * 7) } Else { $Growth168 }
+
+ If ($PoolBalanceObjects | Where-Object { $_.DateTime.Date -eq $Now.Date }) {
+ $GrowthToday = [Double]($PoolBalanceObject.Earnings - ($PoolBalanceObjects | Where-Object { $_.DateTime.Date -eq $Now.Date } | Sort-Object Date | Select-Object -First 1).Earnings)
+ If ($GrowthToday -lt 0) { $GrowthToday = 0 } # to avoid negative numbers
+ }
+
+ $PoolBalanceObjects += $PoolBalanceObject
+ $AllBalanceObjects += $PoolBalanceObject
+ }
+
+ $Balances."$($PoolBalanceObject.Pool) ($($PoolBalanceObject.Currency):$($PoolBalanceObject.Wallet))" = $EarningsObject = [PSCustomObject]@{
+ Pool = $PoolBalanceObject.Pool
+ Wallet = $PoolBalanceObject.Wallet
+ Currency = $PoolBalanceObject.Currency
+ Start = $PoolBalanceObjects[0].DateTime
+ LastUpdated = $PoolBalanceObject.DateTime
+ Pending = [Double]$PoolBalanceObject.Pending
+ Balance = [Double]$PoolBalanceObject.Balance
+ Unpaid = [Double]$PoolBalanceObject.Unpaid
+ Earnings = [Double]$PoolBalanceObject.Earnings
+ Delta = [Double]$PoolBalanceObject.Delta
+ Growth1 = [Double]$Growth1
+ Growth6 = [Double]$Growth6
+ Growth24 = [Double]$Growth24
+ Growth168 = [Double]$Growth168
+ Growth720 = [Double]$Growth720
+ GrowthToday = [Double]$GrowthToday
+ AvgHourlyGrowth = [Double]$AvgHourlyGrowth
+ AvgDailyGrowth = [Double]$AvgDailyGrowth
+ AvgWeeklyGrowth = [Double]$AvgWeeklyGrowth
+ ProjectedEndDayGrowth = If (($Now - $PoolBalanceObjects[0].DateTime).TotalHours -ge 1) { [Double]($AvgHourlyGrowth * ((Get-Date -Hour 0 -Minute 00 -Second 00).AddDays(1).AddSeconds(-1) - $Now).Hours) } Else { [Double]($Growth1 * ((Get-Date -Hour 0 -Minute 00 -Second 00).AddDays(1).AddSeconds(-1) - $Now).Hours) }
+ ProjectedPayDate = If ($PayoutThreshold) { If ([Double]$PoolBalanceObject.Balance -lt $PayoutThreshold * $Variables.Rates.$PayoutThresholdCurrency.($PoolBalanceObject.Currency)) { If (($AvgDailyGrowth, $Growth24 | Measure-Object -Maximum).Maximum -gt 1E-7) { [DateTime]$Now.AddDays(($PayoutThreshold * $Variables.Rates.$PayoutThresholdCurrency.($PoolBalanceObject.Currency) - $PoolBalanceObject.Balance) / (($AvgDailyGrowth, $Growth24) | Measure-Object -Maximum).Maximum) } Else { "Unknown" } } Else { If ($PoolBalanceObject.NextPayout) { $PoolBalanceObject.NextPayout } Else { "Next Payout!" } } } Else { "Unknown" }
+ TrustLevel = [Double]((($Now - $PoolBalanceObjects[0].DateTime).TotalHours / 168), 1 | Measure-Object -Minimum).Minimum
+ TotalHours = [Double]($Now - $PoolBalanceObjects[0].DateTime).TotalHours
+ PayoutThresholdCurrency = $PayoutThresholdCurrency
+ PayoutThreshold = [Double]$PayoutThreshold
+ Payout = [Double]$PoolBalanceObject.Payout
+ Uri = $PoolBalanceObject.Url
+ LastEarnings = If ($Growth24 -gt 0) { $PoolBalanceObject.DateTime } Else { $PoolBalanceObjects[0].DateTime }
+ }
+
+ If ($Config.BalancesTrackerLog -eq $true) {
+ $EarningsObject | Export-Csv -NoTypeInformation -Append ".\Logs\BalancesTrackerLog.csv" -Force -ErrorAction Ignore
+ }
+
+ $PoolTodayEarning = $Earnings | Where-Object Pool -EQ $PoolBalanceObject.Pool | Where-Object Currency -EQ $PoolBalanceObject.Currency | Where-Object Wallet -EQ $PoolBalanceObject.Wallet | Select-Object -Last 1
+
+ If ([String]$PoolTodayEarning.Date -eq $Now.ToLocalTime().ToString("yyyy-MM-dd")) {
+ $PoolTodayEarning.DailyEarnings = [Double]$GrowthToday
+ $PoolTodayEarning.EndTime = $Now.ToLocalTime().ToString("T")
+ $PoolTodayEarning.EndValue = [Double]$PoolBalanceObject.Earnings
+ $PoolTodayEarning.Balance = [Double]$PoolBalanceObject.Balance
+ $PoolTodayEarning.Unpaid = [Double]$PoolBalanceObject.Unpaid
+ $PoolTodayEarning.Payout = [Double]$PoolTodayEarning.Payout + [Double]$PoolBalanceObject.Payout
+ }
+ Else {
+ $Earnings += [PSCustomObject]@{
+ Date = $Now.ToLocalTime().ToString("yyyy-MM-dd")
+ Pool = $EarningsObject.Pool
+ Currency = $EarningsObject.Currency
+ Wallet = $PoolBalanceObject.Wallet
+ DailyEarnings = [Double]$GrowthToday
+ StartTime = $Now.ToLocalTime().ToString("T")
+ StartValue = If ($PoolTodayEarning) { [Double]$PoolTodayEarning.EndValue } Else { [Double]$EarningsObject.Earnings }
+ EndTime = $Now.ToLocalTime().ToString("T")
+ EndValue = [Double]$EarningsObject.Earnings
+ Balance = [Double]$EarningsObject.Balance
+ Pending = [Double]$EarningsObject.Pending
+ Unpaid = [Double]$EarningsObject.Unpaid
+ Payout = [Double]0
+ }
+ }
+
+ Remove-Variable PoolTodayEarning, EarningsObject -ErrorAction Ignore
+ }
+
+ # Always keep pools sorted, even when new pools were added
+ $Variables.Balances = [Ordered]@{ }
+ $Balances.Keys | Where-Object { $Balances.$_.Pool -notin @($Config.BalancesTrackerIgnorePool) } | Sort-Object | ForEach-Object {
+ $Variables.Balances.$_ = $Balances.$_
+ $Variables.PoolsLastEarnings.($_ -replace ' \(.+') = ($Variables.PoolsLastEarnings.($_ -replace ' \(.+'), $Balances.$_.LastEarnings | Measure-Object -Maximum).Maximum
+ }
+ $Variables.PoolsLastEarnings = $Variables.PoolsLastEarnings | Get-SortedObject
+ $Variables.PoolsLastEarnings | ConvertTo-Json | Out-File -FilePath ".\Data\PoolsLastEarnings.json" -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+
+ # Build chart data (used in Web GUI) for last 30 days
+ $PoolChartData = [PSCustomObject]@{ }
+ $ChartData = $Earnings | Where-Object Pool -in $PoolsToTrack | Sort-Object Date | Group-Object -Property Date | Select-Object -Last 30 # days
+
+ # One dataset per pool
+ $ChartData.Group.Pool | Sort-Object -Unique | ForEach-Object {
+ $PoolChartData | Add-Member @{ $_ = [Double[]]@() }
+ }
+
+ # Fill dataset
+ ForEach ($PoolEarnings in $ChartData) {
+ $PoolChartData.PSObject.Properties.Name | ForEach-Object {
+ $PoolChartData.$_ += ($PoolEarnings.Group | Where-Object Pool -EQ $_ | ForEach-Object { [Double]$_.DailyEarnings * $Variables.Rates.($_.Currency).BTC } | Measure-Object -Sum).Sum
+ }
+ }
+
+ $Variables.EarningsChartData = [PSCustomObject]@{
+ # CumulatedEarnings = $CumulatedEarnings
+ Currency = $Config.Currency
+ BTCrate = [Double]$Variables.Rates.BTC.($Config.Currency)
+ Labels = @(
+ $ChartData.Group.Date | Sort-Object -Unique | ForEach-Object {
+ [DateTime]::parseexact($_, "yyyy-MM-dd", $null).ToShortDateString()
+ }
+ )
+ # Use dates for x-axis label
+ Earnings = $PoolChartData
+ }
+
+ $Variables.EarningsChartData | ConvertTo-Json | Out-File -FilePath ".\Data\EarningsChartData.json" -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+
+ # At least 31 days are needed for Growth720
+ If ($AllBalanceObjects.Count -gt 1) {
+ $AllBalanceObjects = @(
+ $AllBalanceObjects | Where-Object DateTime -GE $Now.AddDays(-31) | Sort-Object DateTime | ForEach-Object {
+ If ($_.Delta -ne 0 -or $_.DateTime.Date -eq $Now.Date) { $_ } # keep with delta <> 0
+ ElseIf ($Record -and $_.DateTime.Date -ne $Record.DateTime.Date) { $_ } # keep the newest one per day
+ $Record = $_
+ }
+ ) | Sort-Object DateTime -Descending
+ }
+
+ Try {
+ $Earnings | Export-Csv ".\Data\DailyEarnings.csv" -NoTypeInformation -Force -ErrorAction Ignore
+ }
+ Catch {
+ Write-Message -Level Warn "Balances Tracker failed to save earnings data to '.\Data\DailyEarnings.csv' (should have $($Earnings.count) entries)."
+ }
+
+ If ($AllBalanceObjects.Count -ge 1) { $AllBalanceObjects | ConvertTo-Json | Out-File -FilePath ".\Data\BalancesTrackerData.json" -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue }
+ $Variables.BalanceData = $AllBalanceObjects
+
+ # Sleep until next update (at least 1 minute, maximum 60 minutes)
+ While ((Get-Date).ToUniversalTime() -le $Now.AddMinutes((60, (1, [Int]$Config.BalancesTrackerPollInterval | Measure-Object -Maximum).Maximum | Measure-Object -Minimum).Minimum)) { Start-Sleep -Seconds 5 }
+ }
+}
+
+Write-Message -Level Info "Balances Tracker stopped."
diff --git a/Includes/CPUID.cs b/Includes/CPUID.cs
new file mode 100644
index 0000000000..7fbf0121ba
--- /dev/null
+++ b/Includes/CPUID.cs
@@ -0,0 +1,160 @@
+using System;
+using System.Runtime.InteropServices;
+
+public static class CpuID
+{
+ public static byte[] Invoke(int level)
+ {
+ IntPtr codePointer = IntPtr.Zero;
+ try
+ {
+ // compile
+ byte[] codeBytes;
+ if (IntPtr.Size == 4)
+ {
+ codeBytes = x86CodeBytes;
+ }
+ else
+ {
+ codeBytes = x64CodeBytes;
+ }
+
+ codePointer = VirtualAlloc(
+ IntPtr.Zero,
+ new UIntPtr((uint)codeBytes.Length),
+ AllocationType.COMMIT | AllocationType.RESERVE,
+ MemoryProtection.EXECUTE_READWRITE
+ );
+
+ Marshal.Copy(codeBytes, 0, codePointer, codeBytes.Length);
+
+ CpuIDDelegate cpuIdDelg = (CpuIDDelegate)Marshal.GetDelegateForFunctionPointer(codePointer, typeof(CpuIDDelegate));
+
+ // invoke
+ GCHandle handle = default(GCHandle);
+ var buffer = new byte[16];
+
+ try
+ {
+ handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ cpuIdDelg(level, buffer);
+ }
+ finally
+ {
+ if (handle != default(GCHandle))
+ {
+ handle.Free();
+ }
+ }
+
+ return buffer;
+ }
+ finally
+ {
+ if (codePointer != IntPtr.Zero)
+ {
+ VirtualFree(codePointer, 0, 0x8000);
+ codePointer = IntPtr.Zero;
+ }
+ }
+ }
+
+ [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
+ private delegate void CpuIDDelegate(int level, byte[] buffer);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationType flAllocationType,
+ MemoryProtection flProtect);
+
+ [DllImport("kernel32")]
+ private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, UInt32 dwFreeType);
+
+ [Flags()]
+ private enum AllocationType : uint
+ {
+ COMMIT = 0x1000,
+ RESERVE = 0x2000,
+ RESET = 0x80000,
+ LARGE_PAGES = 0x20000000,
+ PHYSICAL = 0x400000,
+ TOP_DOWN = 0x100000,
+ WRITE_WATCH = 0x200000
+ }
+
+ [Flags()]
+ private enum MemoryProtection : uint
+ {
+ EXECUTE = 0x10,
+ EXECUTE_READ = 0x20,
+ EXECUTE_READWRITE = 0x40,
+ EXECUTE_WRITECOPY = 0x80,
+ NOACCESS = 0x01,
+ READONLY = 0x02,
+ READWRITE = 0x04,
+ WRITECOPY = 0x08,
+ GUARD_Modifierflag = 0x100,
+ NOCACHE_Modifierflag = 0x200,
+ WRITECOMBINE_Modifierflag = 0x400
+ }
+
+ /*
+ Basic ASM strategy
+ void x86CpuId(int level, byte* buffer)
+ {
+ eax = level
+ cpuid
+ buffer[0] = eax
+ buffer[4] = ebx
+ buffer[8] = ecx
+ buffer[12] = edx
+ }
+ */
+
+ private readonly static byte[] x86CodeBytes = {
+ 0x55, // push ebp
+ 0x8B, 0xEC, // mov ebp,esp
+ 0x53, // push ebx
+ 0x57, // push edi
+
+ 0x8B, 0x45, 0x08, // mov eax, dword ptr [ebp+8] (move level into eax)
+ 0x0F, 0xA2, // cpuid
+
+ 0x8B, 0x7D, 0x0C, // mov edi, dword ptr [ebp+12] (move address of buffer into edi)
+ 0x89, 0x07, // mov dword ptr [edi+0], eax (write eax, ... to buffer)
+ 0x89, 0x5F, 0x04, // mov dword ptr [edi+4], ebx
+ 0x89, 0x4F, 0x08, // mov dword ptr [edi+8], ecx
+ 0x89, 0x57, 0x0C, // mov dword ptr [edi+12],edx
+
+ 0x5F, // pop edi
+ 0x5B, // pop ebx
+ 0x8B, 0xE5, // mov esp,ebp
+ 0x5D, // pop ebp
+ 0xc3 // ret
+ };
+
+ private readonly static byte[] x64CodeBytes = {
+ 0x53, // push rbx this gets clobbered by cpuid
+
+ // rcx is level.
+ // rdx is buffer.
+ // Need to save buffer elsewhere, cpuid overwrites rdx.
+ // Put buffer in r8, use r8 to reference buffer later.
+
+ // Save rdx (buffer addy) to r8
+ 0x49, 0x89, 0xd0, // mov r8, rdx
+
+ // Move ecx (level) to eax to call cpuid, call cpuid
+ 0x89, 0xc8, // mov eax, ecx
+ 0xB9, 0x00, 0x00, 0x00, 0x00, // mov ecx, 0
+ 0x0F, 0xA2, // cpuid
+
+ // Write eax et al to buffer
+ 0x41, 0x89, 0x40, 0x00, // mov dword ptr [r8+0], eax
+ 0x41, 0x89, 0x58, 0x04, // mov dword ptr [r8+4], ebx
+ 0x41, 0x89, 0x48, 0x08, // mov dword ptr [r8+8], ecx
+ 0x41, 0x89, 0x50, 0x0c, // mov dword ptr [r8+12], edx
+
+ 0x5b, // pop rbx
+ 0xc3 // ret
+ };
+}
diff --git a/Includes/Core.ps1 b/Includes/Core.ps1
new file mode 100644
index 0000000000..24b64edb05
--- /dev/null
+++ b/Includes/Core.ps1
@@ -0,0 +1,1278 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: Core.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+using module .\Include.psm1
+using module .\API.psm1
+
+$ProgressPreference = "SilentlyContinue"
+
+Get-ChildItem -Path ".\Includes\MinerAPIs" -File | ForEach-Object { . $_.FullName }
+
+While ($Variables.NewMiningStatus -eq "Running") {
+
+ $Variables.LogFile = "$($Variables.MainPath)\Logs\$($Variables.Branding.ProductLabel)_$(Get-Date -Format "yyyy-MM-dd").log"
+
+ # Always get the latest config
+ Read-Config -ConfigFile $Variables.ConfigFile
+
+ If ($Config.MineWhenIdle -and $Variables.IdleRunspace -and $Variables.IdleRunspace.NewMiningStatus -eq "Mining" -and $Variables.NewMiningStatus -eq "Running") {
+ $Variables.IdleRunspace | Add-Member MiningStatus "Mining" -Force
+ Write-Message -Level Info "Started new cycle (System was idle for $($Config.IdleSec) seconds)."
+ }
+ Else {
+ Write-Message -Level Info "Started new cycle."
+ }
+
+ If ($Config.MineWhenIdle) {
+ If (-not $Variables.IdleRunspace) {
+ Start-IdleDetection
+ }
+ }
+ ElseIf ($Variables.IdleRunspace) {
+ Stop-IdleDetection
+ }
+
+ # Faster shutdown
+ If ($Variables.NewMiningStatus -ne "Running" -or $Variables.IdleRunspace.NewMiningStatus -eq "Idle") { Break }
+
+ While ($Variables.IdleRunspace.NewMiningStatus -ne "Idle") {
+
+ # Prepare devices
+ $Variables.EnabledDevices = $Variables.Devices | Where-Object { $_.State -eq [DeviceState]::Enabled } | ConvertTo-Json -Depth 10 | ConvertFrom-Json
+ # For GPUs set type AMD or NVIDIA
+ $Variables.EnabledDevices | Where-Object Type -EQ "GPU" | ForEach-Object { $_.Type = $_.Vendor }
+ # Remove model information from devices -> will create only one miner instance
+ If (-not $Config.MinerInstancePerDeviceModel) { $Variables.EnabledDevices | ForEach-Object { $_.Model = $_.Vendor } }
+
+ #Much faster
+ $Pools = [Pool[]]$Variables.Pools
+
+ # Skip stuff if previous cycle was shorter than half of what it should
+ If (-not $Variables.Pools -or -not $Variables.Miners -or -not $Variables.Timer -or $Variables.Timer.AddSeconds([Int]($Config.Interval / 2)) -lt (Get-Date).ToUniversalTime() -or (Compare-Object @($Config.ExtraCurrencies | Select-Object) @($Variables.AllCurrencies | Select-Object) | Where-Object SideIndicator -eq "<=")) {
+
+ # Set master timer
+ $Variables.Timer = (Get-Date).ToUniversalTime()
+ $Variables.EndLoopTime = $Variables.Timer.AddSeconds($Config.Interval)
+
+ $Variables.CycleStarts += $Variables.Timer
+ $Variables.CycleStarts = @($Variables.CycleStarts | Select-Object -Last (3, ($Config.SyncWindow + 1) | Measure-Object -Maximum).Maximum)
+ $Variables.SyncWindowDuration = (($Variables.CycleStarts | Select-Object -Last 1) - ($Variables.CycleStarts | Select-Object -First 1))
+
+ # Set minimum Watchdog minimum count 3
+ $Variables.WatchdogCount = (3, $Config.WatchdogCount | Measure-Object -Maximum).Maximum
+ $Variables.WatchdogReset = $Variables.WatchdogCount * $Variables.WatchdogCount * $Variables.WatchdogCount * $Variables.WatchdogCount * $Config.Interval
+
+ # Expire watchdog timers
+ If ($Config.Watchdog) { $Variables.WatchdogTimers = @($Variables.WatchdogTimers | Where-Object { $Config.WatchDog } | Where-Object Kicked -GE $Variables.Timer.AddSeconds( - $Variables.WatchdogReset)) }
+ Else { $Variables.WatchdogTimers = @() }
+
+ If (-not $Variables.DAGdata) { $Variables.DAGdata = [PSCustomObject][Ordered]@{ } }
+ If (-not $Variables.DAGdata.Currency) { $Variables.DAGdata | Add-Member Currency ([Ordered]@{ }) -Force }
+
+ # Do do once every 24hrs or if unable to get data from all sources
+ If ($Variables.DAGdata.Updated_Minerstat -lt (Get-Date).AddDays(-1)) {
+ Try {
+ $Request = Invoke-WebRequest -Uri "https://minerstat.com/dag-size-calculator" -TimeoutSec 5 # PWSH 6+ no longer supports basic parsing -> parse text
+ $Request.Content -split '\n' -replace '"', "'" | Where-Object { $_ -like ".*$"
+ $BlockHeight = [Int]($_ -replace "^
" -replace "
")
+ $DAGsize = Get-DAGsize $BlockHeight $Currency
+ # Epoch for EtcHash is twice as long
+ $Epoch = If ($Currency -eq "ETC") { [Int][Math]::Floor($BlockHeight / 60000) } Else { [Int][Math]::Floor($BlockHeight / 30000) }
+
+ If ($BlockHeight -and $Currency -and $DAGsize -and $Epoch) {
+ $Data = [PSCustomObject]@{
+ BlockHeight = [Int]$BlockHeight
+ CoinName = Get-CoinName $Currency
+ DAGsize = [Int64]$DAGsize
+ Epoch = [Int]$Epoch
+ }
+ $Variables.DAGdata.Currency.Remove($Currency)
+ $Variables.DAGdata.Currency.Add($Currency, $Data)
+ }
+ }
+ $Variables.DAGdata | Add-Member Updated_Minerstat (Get-Date).ToUniversalTime() -Force
+ Write-Message -Level Info "Loaded DAG block data from 'https://minerstat.com'."
+ }
+ Catch {
+ Write-Message -Level Warn "Cannot load DAG block data from 'https://minerstat.com'."
+ }
+ }
+
+ If ($Variables.DAGdata.Updated_RavenCoin -lt (Get-Date).AddDays(-1)) {
+ Try {
+ # Get RVN block data
+ $Request = "https://api.ravencoin.org/api/status"
+
+ If ($BlockHeight = [Int](Invoke-RestMethod -Uri $Request -TimeoutSec 5).Info.blocks) {
+ $Data = [PSCustomObject][Ordered]@{
+ BlockHeight = [Int]$BlockHeight
+ CoinName = Get-CoinName "RVN"
+ DAGsize = Get-DAGSize -Block $BlockHeight -Coin "RVN"
+ Epoch = [Int][Math]::Floor($BlockHeight / 7500)
+ }
+ $Variables.DAGdata.Currency.Remove("RVN")
+ $Variables.DAGdata.Currency.Add("RVN", $Data)
+ $Variables.DAGdata | Add-Member Updated_Ravencoin (Get-Date).ToUniversalTime() -Force
+ Write-Message -Level Info "Loaded RVN DAG block data from 'https://api.ravencoin.org'."
+ }
+ }
+ Catch {
+ Write-Message -Level Warn "Cannot load RVN DAG block data from 'https://api.ravencoin.org'."
+ }
+ }
+
+ If ($Request) {
+ # Add default '*' (equal to highest)
+ If ($Variables.DAGdata.Currency.Count -gt 1) {
+ $Data = [PSCustomObject][Ordered]@{
+ BlockHeight = [Int]($Variables.DAGdata.Currency.Keys | ForEach-Object { $Variables.DAGdata.Currency.$_.BlockHeight } | Measure-Object -Maximum).Maximum
+ CoinName = "*"
+ DAGsize = [Int64]($Variables.DAGdata.Currency.Keys | ForEach-Object { $Variables.DAGdata.Currency.$_.DAGsize } | Measure-Object -Maximum).Maximum
+ Epoch = [Int]($Variables.DAGdata.Currency.Keys | ForEach-Object { $Variables.DAGdata.Currency.$_.Epoch } | Measure-Object -Maximum).Maximum
+ }
+ $Variables.DAGdata.Currency.Remove("*")
+ $Variables.DAGdata.Currency.Add("*", $Data)
+ $Variables.DAGdata | ConvertTo-Json -ErrorAction Ignore | Out-File -FilePath ".\Data\DagData.json" -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+ }
+ ElseIf ((Get-ChildItem -Path ".\Data\DagData.json" -ErrorAction Ignore).LastWriteTime.AddDays(1) -gt (Get-Date)) {
+ # Read from file
+ $Variables.DAGdata = Get-Content ".\Data\DagData.json" -ErrorAction Ignore | ConvertFrom-Json -ErrorAction Ignore
+ If ($Variables.DAGdata) { Write-Message -Level Verbose "Loaded DAG block data from cached file '.\Data\DagData.json'." }
+ }
+
+ If (-not $Variables.DAGdata.Currency."*") {
+ If (-not $Variables.DAGdata.Currency) {
+ $Variables.DAGdata = [PSCustomObject][Ordered]@{ }
+ $Variables.DAGdata | Add-Member Currency ([Ordered]@{ })
+ }
+
+ $BlockHeight = ((Get-Date) - [DateTime]"07/31/2015").Days * 6400
+ Write-Message -Level Warn "Cannot load ethash DAG size information from 'https://minerstat.com', using calculated block height $BlockHeight based on 6400 blocks per day since 30 July 2015."
+ $Data = [PSCustomObject]@{
+ BlockHeight = [Int]$BlockHeight
+ CoinName = "Ethereum"
+ DAGsize = Get-DAGSize $BlockHeight
+ Epoch = [Int][Math]::Floor($BlockHeight / 30000)
+ }
+ $Variables.DAGdata.Currency.Add("*", $Data)
+ }
+ }
+ Remove-Variable BlockHeight, Currency, DAGdata, DAGSize, Data, Epoch, Request -ErrorAction Ignore
+
+ # Use non-donate pool config
+ $Variables.NiceHashWalletIsInternal = $Config.NiceHashWalletIsInternal
+ $PoolNames = If ($Variables.NiceHashWalletIsInternal) { $Config.PoolName -replace "NiceHash", "NiceHash Internal" } Else { $Config.PoolName -replace "NiceHash", "NiceHash External" }
+ $PoolsConfig = $Config.PoolsConfig
+
+ If ($Config.Donate -gt 0) {
+ # Re-Randomize donation start once per day, do not donate if remaing time for today is less than donation duration
+ If (($Variables.DonateStart).Date -ne (Get-Date).Date -and (Get-Date).AddMinutes($Config.Donate).Date -eq (Get-Date).Date) {
+ $Variables.DonateStart = (Get-Date).AddMinutes((Get-Random -Minimum $Config.Donate -Maximum (1440 - $Config.Donate - (Get-Date).TimeOfDay.TotalMinutes))).ToUniversalTime()
+ $Variables.DonateEnd = $null
+ }
+
+ If ((Get-Date).ToUniversalTime() -ge $Variables.DonateStart -and $null -eq $Variables.DonateEnd) {
+ # We get here only once per day, ensure full donation period
+ $Variables.DonateStart = (Get-Date).ToUniversalTime()
+ $Variables.DonateEnd = $Variables.DonateStart.AddMinutes($Config.Donate)
+
+ # Add pool config to config (in-memory only)
+ Get-DonationPoolConfig
+
+ # Clear all pools
+ $Variables.Pools = [Pool[]]@()
+ }
+ }
+
+ If ($Variables.DonateRandom) {
+ If ((Get-Date).ToUniversalTime() -ge $Variables.DonateStart -and (Get-Date).ToUniversalTime() -lt $Variables.DonateEnd) {
+ # Ensure full donation period
+ $Variables.EndLoopTime = $Variables.DonateEnd
+ # Activate donation
+ $PoolNames = $Variables.DonatePoolsConfig.Keys -replace "Nicehash", "NiceHash External"
+ $PoolsConfig = $Variables.DonatePoolsConfig
+ $Variables.NiceHashWalletIsInternal = $false
+ Write-Message -Level Info "Donation run: Mining for '$($Variables.DonateRandom.Name)' for the next $(If (($Config.Donate - ((Get-Date) - $Variables.DonateStart).Minutes) -gt 1) { "$($Config.Donate - ((Get-Date) - $Variables.DonateStart).Minutes) minutes" } Else { "minute" }). $($Variables.Branding.ProductLabel) will use these pools while donating: '$($PoolNames -join ', ')'."
+ }
+ ElseIf ((Get-Date).ToUniversalTime() -gt $Variables.DonateEnd) {
+ $Variables.DonatePoolsConfig = $null
+ $Variables.DonateRandom = $null
+ Write-Message -Level Info "Donation run complete - thank you! Mining for you again. :-)"
+
+ # Clear all pools
+ $Variables.Pools = [Pool[]]@()
+ }
+ }
+
+ # Stop BrainJobs for deconfigured pools
+ Stop-BrainJob @($Variables.BrainJobs.Keys | Where-Object { $_ -notin $PoolNames })
+
+ # Faster shutdown
+ If ($Variables.NewMiningStatus -ne "Running" -or $Variables.IdleRunspace.NewMiningStatus -eq "Idle") { Break }
+
+ # Start Brain jobs (will pick up all newly added pools)
+ Start-BrainJob $PoolNames
+
+ # Clear pools if pools config has changed to avoid double pools with different wallets/usernames
+ If (($Config.PoolsConfig | ConvertTo-Json -Depth 10 -Compress) -ne ($PoolsConfig | ConvertTo-Json -Depth 10 -Compress)) { $Variables.Pools = [Miner]::Pools }
+
+ # Load information about the pools
+ If ($PoolNames) {
+ If ($Variables.Pools) {
+ Write-Message -Level Verbose "Loading pool data from '$($PoolNames -join ', ')'..."
+ }
+ Else {
+ If ($Variables.BrainJobs.Keys) {
+ # Allow extra 30 seconds for brains to get ready
+ $Variables.Summary = "Loading pool data from '$($PoolNames -join ', ')'. This will take more than 30 seconds..."
+ Write-Message -Level Verbose $Variables.Summary
+ Start-Sleep -Seconds 30
+ }
+ Else {
+ $Variables.Summary = "Loading pool data from '$($PoolNames -join ', ')'..."
+ Write-Message -Level Verbose $Variables.Summary
+ }
+ }
+ $NewPools_Jobs = @(
+ $PoolNames | ForEach-Object {
+ Get-ChildItemContent ".\Pools\$((Get-PoolBaseName $_) -replace "^NiceHash .*", "NiceHash").*" -Parameters @{ Config = $Config; PoolsConfig = $PoolsConfig; PoolVariant = $_; Variables = $Variables } -Threaded -Priority $(If ($Variables.Miners | Where-Object { $_.Status -eq [MinerStatus]::Running } | Where-Object Type -EQ "CPU") { "Normal" })
+ }
+ )
+ }
+ Else {
+ Write-Message -Level Warn "No configured pools!"
+ }
+
+ # Load currency exchange rates from min-api.cryptocompare.com
+ Get-Rate
+
+ # Power cost preparations
+ $Variables.CalculatePowerCost = $Config.CalculatePowerCost # $Variables.CalculatePowerCost is an operational variable and not identical to $Config.CalculatePowerCost
+ If ($Config.CalculatePowerCost -eq $true) {
+ If ($Variables.EnabledDevices.Count -ge 1) {
+ # HWiNFO64 verification
+ $RegKey = "HKCU:\Software\HWiNFO64\VSB"
+ If ($RegValue = Get-ItemProperty -Path $RegKey -ErrorAction SilentlyContinue) {
+ If ([String]$Variables.HWInfo64RegValue -eq [String]$RegValue) {
+ Write-Message -Level Warn "Power usage info in registry has not been updated [HWiNFO64 not running???] - disabling power usage calculations."
+ $Variables.CalculatePowerCost = $false
+ }
+ Else {
+ $Hashtable = @{ }
+ $DeviceName = ""
+ $RegValue.PSObject.Properties | Where-Object { $_.Name -match "^Label[0-9]+$" -and (Compare-Object @($_.Value -split ' ' | Select-Object) @($Variables.EnabledDevices.Name | Select-Object) -IncludeEqual -ExcludeDifferent) } | ForEach-Object {
+ $DeviceName = ($_.Value -split ' ') | Select-Object -Last 1
+ Try {
+ $Hashtable.Add($DeviceName, $RegValue.($_.Name -replace "Label", "Value"))
+ }
+ Catch {
+ Write-Message -Level Warn "HWiNFO64 sensor naming is invalid [duplicate sensor for $DeviceName] - disabling power usage calculations."
+ $Variables.CalculatePowerCost = $false
+ }
+ }
+ # Add configured power usage
+ $Config.PowerUsage.PSObject.Properties.Name | Where-Object { $Config.PowerUsage.$_ } | ForEach-Object {
+ If ($Config.PowerUsage.$_) {
+ If ($_ -in @($Variables.EnabledDevices.Name) -and -not $Hashtable.$_) { Write-Message -Level Warn "HWiNFO64 cannot read power usage from system for device ($_). Will use configured value of $([Double]$Config.PowerUsage.$_) W." }
+ $Hashtable.$_ = "$Config.PowerUsage.$_ W"
+ If ($Variables.EnabledDevices | Where-Object Name -EQ $_) { ($Variables.EnabledDevices | Where-Object Name -EQ $_).ConfiguredPowerUsage = [Double]$Config.PowerUsage.$_ }
+ }
+ }
+
+ If ($DeviceNamesMissingSensor = Compare-Object @($Variables.EnabledDevices.Name) @($Hashtable.Keys) -PassThru | Where-Object SideIndicator -EQ "<=") {
+ Write-Message -Level Warn "HWiNFO64 sensor naming is invalid [missing sensor config for $($DeviceNamesMissingSensor -join ', ')] - disabling power usage calculations."
+ $Variables.CalculatePowerCost = $false
+ }
+
+ # Enable read power usage for configured devices
+ $Variables.Devices | ForEach-Object { $_.ReadPowerUsage = $_.Name -in @($Hashtable.Keys) }
+
+ Remove-Variable DeviceName, DeviceNamesMissingSensor, Hashtable
+ }
+ $Variables.HWInfo64RegValue = [String]$RegValue
+ }
+ Else {
+ Write-Message -Level Warn "Cannot read power usage info from registry [Key '$RegKey' does not exist - HWiNFO64 not running???] - disabling power usage calculations."
+ $Variables.CalculatePowerCost = $false
+ }
+ Remove-Variable RegKey, RegValue
+ }
+ Else { $Variables.CalculatePowerCost = $false }
+ }
+ If (-not $Variables.CalculatePowerCost) {
+ $Variables.Devices | ForEach-Object { $_.ReadPowerUsage = $false }
+ }
+
+ # Power price
+ If (-not (($Config.PowerPricekWh | Get-Member -MemberType NoteProperty -ErrorAction Ignore).Name)) { $Config.PowerPricekWh = [PSCustomObject]@{ "00:00" = 0 } }
+ If ($null -eq $Config.PowerPricekWh."00:00") {
+ # 00:00h power price is the same as the latest price of the previous day
+ $Config.PowerPricekWh | Add-Member "00:00" (($Config.PowerPricekWh.($Config.PowerPricekWh | Get-Member -MemberType NoteProperty -ErrorAction Ignore).Name | Sort-Object | Select-Object -Last 1))
+ }
+ $Variables.PowerPricekWh = [Double]($Config.PowerPricekWh.(($Config.PowerPricekWh | Get-Member -MemberType NoteProperty -ErrorAction Ignore).Name | Sort-Object | Where-Object { $_ -lt (Get-Date -Format HH:mm).ToString() } | Select-Object -Last 1))
+ $Variables.PowerCostBTCperW = [Double](1 / 1000 * 24 * $Variables.PowerPricekWh / $Variables.Rates."BTC".($Config.Currency))
+ $Variables.BasePowerCostBTC = [Double]($Config.IdlePowerUsageW / 1000 * 24 * $Variables.PowerPricekWh / $Variables.Rates."BTC".($Config.Currency))
+
+ # Load unprofitable algorithms
+ Try {
+ $Variables.UnprofitableAlgorithms = Get-Content -Path ".\Data\UnprofitableAlgorithms.json" -ErrorAction Ignore | ConvertFrom-Json -ErrorAction Stop -AsHashtable | Select-Object | Get-SortedObject
+ Write-Message -Level Info "Loaded list of unprofitable algorithms ($($Variables.UnprofitableAlgorithms.Count) $(If ($Variables.UnprofitableAlgorithms.Count -ne 1) { "entries" } Else { "entry" }))."
+ }
+ Catch {
+ Write-Message -Level ERROR "Error loading list of unprofitable algorithms. File '.\Data\UnprofitableAlgorithms.json' is not a valid $($Variables.Branding.ProductLabel) JSON data file. Please restore it from your original download."
+ $Variables.UnprofitableAlgorithms = $null
+ }
+
+ # Send data to monitoring server
+ If ($Config.ReportToServer) { Send-MonitoringData }
+
+ # Read all stats, will remove those from memory that no longer exist as file
+ Get-Stat
+
+ # Retrieve collected pool data
+ $Variables.PoolTimeout = [Int]$Config.PoolTimeout
+ If ($Variables.Miners | Where-Object { $_.Status -eq [MinerStatus]::Running } | Where-Object Type -EQ "CPU") { $Variables.PoolTimeout * 2 } # Double allowed time if CPU miner is running to avoid timeouts
+ $Variables.NewPools = @($NewPools_Jobs | ForEach-Object { $_ | Get-Job -ErrorAction Ignore | Wait-Job -Timeout $Variables.PoolTimeout | Receive-Job } | ForEach-Object { $_.Content -as [Pool] })
+ $NewPools_Jobs | ForEach-Object { $_ | Get-Job -ErrorAction Ignore | Remove-Job -Force }
+ Remove-Variable NewPools_Jobs -ErrorAction Ignore
+
+ $Variables.NewPools | ForEach-Object {
+ $_.CoinName = Get-CoinName $_.Currency
+ $_.Fee = If ($Config.IgnorePoolFee -or $_.Fee -lt 0 -or $_.Fee -gt 1) { 0 } Else { $_.Fee }
+ $Factor = $_.EarningsAdjustmentFactor * (1 - $_.Fee)
+ $_.Price = $_.Price * $Factor
+ $_.Price_Bias = $_.Price * $_.Accuracy
+ $_.StablePrice = $_.StablePrice * $Factor
+ }
+
+ If ($PoolNoData = @(Compare-Object @($PoolNames) @($Variables.NewPools.Name | Sort-Object -Unique) -PassThru)) {
+ Write-Message -Level Warn "No data received from pool$(If ($PoolNoData.Count -gt 1) { "s" }) '$($PoolNoData -join ', ')'."
+ }
+ Remove-Variable PoolNoData -ErrorAction Ignore
+
+ # Faster shutdown
+ If ($Variables.NewMiningStatus -ne "Running" -or $Variables.IdleRunspace.NewMiningStatus -eq "Idle") { Break }
+
+ # Anycast changed, remove all pools because best pool sort cannot handle anycast AND regional pools, also helps keeping total pool number down
+ If ($Variables.UseAnycast -ne $Config.UseAnycast) {
+ $Pools = [Pool[]]@()
+ }
+ $Variables.UseAnycast = $Config.UseAnycast
+
+ # Remove de-configured pools
+ $Pools = $Pools | Where-Object Name -in $PoolNames
+
+ If ($ComparePools = @(Compare-Object -PassThru @($Variables.NewPools | Select-Object) @($Pools | Select-Object) -Property Name, Algorithm, Host, Port, SSL -IncludeEqual)) {
+ # Find new pools
+ $Variables.AddedPools = @($ComparePools | Where-Object SideIndicator -eq "<=" | ForEach-Object { $_.PSObject.Properties.Remove('SideIndicator'); $_ })
+ $Variables.UpdatedPools = @($ComparePools | Where-Object SideIndicator -eq "==" | ForEach-Object { $_.PSObject.Properties.Remove('SideIndicator'); $_ })
+
+ # Add new pools
+ $Pools += $Variables.AddedPools
+
+ $Variables.PoolsCount = $Pools.Count
+
+ # Update existing pools
+ $Pools | Select-Object | ForEach-Object {
+ $_.Available = $true
+ $_.Best = $false
+ $_.Reason = $null
+
+ If ($Pool = $Variables.UpdatedPools | Where-Object Name -EQ $_.Name | Where-Object Algorithm -EQ $_.Algorithm | Where-Object Host -EQ $_.Host | Where-Object Port -EQ $_.Port | Where-Object SSL -EQ $_.SSL | Select-Object -First 1) {
+ $_.Accuracy = $Pool.Accuracy
+ $_.CoinName = $Pool.CoinName
+ $_.Currency = $Pool.Currency
+ $_.EarningsAdjustmentFactor = $Pool.EarningsAdjustmentFactor
+ $_.Fee = $Pool.Fee
+ $_.Pass = $Pool.Pass
+ $_.Price = $Pool.Price
+ $_.Price_Bias = $Pool.Price_Bias
+ $_.StablePrice = $Pool.StablePrice
+ $_.Updated = $Pool.Updated
+ $_.User = $Pool.User
+ $_.Workers = $Pool.Workers
+ }
+
+ If ($Variables.DAGdata.Currency.($_.Currency).BlockHeight) {
+ $_.BlockHeight = $Variables.DAGdata.Currency.($_.Currency).BlockHeight
+ $_.Epoch = $Variables.DAGdata.Currency.($_.Currency).Epoch
+ $_.DAGSize = $Variables.DAGdata.Currency.($_.Currency).DAGsize
+ }
+ ElseIf ($_.Algorithm -eq "EthashLowMem") {
+ $_.BlockHeight = 0
+ $_.Epoch = 0
+ $_.DAGSize = $Config.EthashLowMemMinMemGB # ProHashing sometimes does not like GPUs with very little VRAM
+ }
+ ElseIf ($_.Algorithm -in @("EtcHash", "Ethash", "KawPoW", "ProgPoW", "UbqHash")) {
+ $_.BlockHeight = $Variables.DAGdata.Currency."*".BlockHeight
+ $_.Epoch = $Variables.DAGdata.Currency."*".Epoch
+ $_.DAGSize = $Variables.DAGdata.Currency."*".DAGsize
+ }
+ }
+ Remove-Variable Factor, Pool -ErrorAction Ignore
+
+ # Pool data is older than earliest CycleStart, decay price
+ If ($Variables.CycleStarts.Count -ge $Config.SyncWindow) {
+ $MaxPoolAge = $Config.SyncWindow * ($Variables.CycleStarts[-1] - $Variables.CycleStarts[0]).TotalMinutes
+ $Pools = $Pools | Where-Object { [Math]::Floor(($Variables.CycleStarts[-1] - $_.Updated).TotalMinutes) -le $MaxPoolAge * $Config.SyncWindow * $Config.SyncWindow }
+ $Pools | ForEach-Object {
+ If ([Math]::Floor(($Variables.CycleStarts[-1] - $_.Updated).TotalMinutes) -gt $MaxPoolAge) { $_.Reason += "Data too old" }
+ ElseIf ($_.Updated -lt $Variables.CycleStarts[0]) { $_.Price_Bias = $_.Price * $_.Accuracy * [Math]::Pow(0.9, ($Variables.CycleStarts[0] - $_.Updated).TotalMinutes) }
+ }
+ Remove-Variable MaxPoolAge -ErrorAction Ignore
+ }
+
+ # Pool disabled by stat file
+ $Pools | Where-Object Disabled -EQ $true | ForEach-Object { $_.Reason += "Disabled (by Stat file)" }
+ # Min accuracy not reached
+ $Pools | Where-Object Accuracy -LT $Config.MinAccuracy | ForEach-Object { $_.Reason += "MinAccuracy ($($Config.MinAccuracy * 100)%) not reached" }
+ # Unavailable algorithms
+ $Pools | Where-Object { $Variables.UnprofitableAlgorithms.($_.Algorithm) -eq "*" } | ForEach-Object { $_.Reason += "Unprofitable Algorithm" }
+ # Pool price 0
+ $Pools | Where-Object Price -EQ 0 | ForEach-Object { $_.Reason += "Price -eq 0" }
+ # No price data
+ $Pools | Where-Object Price -EQ [Double]::NaN | ForEach-Object { $_.Reason += "No price data" }
+ # Ignore pool if price is more than $Config.UnrealPoolPriceFactor higher than second highest price of all other pools with same algorithm; NiceHash & MiningPoolHub are always right
+ If ($Config.UnrealPoolPriceFactor -gt 1 -and ($Pools.BaseName | Sort-Object -Unique).Count -gt 1) {
+ $Pools | Where-Object Price_Bias -GT 0 | Group-Object -Property Algorithm | ForEach-Object {
+ If (($_.Group.BaseName | Sort-Object -Unique).Count -ge 3 -and ($PriceThreshold = @($_.Group.Price_Bias | Sort-Object -Unique)[-2] * $Config.UnrealPoolPriceFactor)) {
+ $_.Group | Where-Object { $_.BaseName -notmatch "NiceHash *|MiningPoolHub" } | Where-Object Price_Bias -GT $PriceThreshold | ForEach-Object { $_.Reason += "Unreal price ($($Config.UnrealPoolPriceFactor)x higher than second highest price)" }
+ }
+ }
+ }
+ Remove-Variable PriceThreshold -ErrorAction SilentlyContinue
+ # Algorithms disabled
+ $Pools | Where-Object { "-$($_.Algorithm)" -in $Config.Algorithm } | ForEach-Object { $_.Reason += "Algorithm disabled (``-$($_.Algorithm)`` in generic config)" }
+ $Pools | Where-Object { "-$($_.Algorithm)" -in $PoolsConfig.$(Get-PoolBaseName $_.BaseName).Algorithm } | ForEach-Object { $_.Reason += "Algorithm disabled (``-$($_.Algorithm)`` in $($_.BaseName) pool config)" }
+ # Algorithms not enabled
+ If ($Config.Algorithm -like "+*") { $Pools | Where-Object { "+$($_.Algorithm)" -notin $Config.Algorithm } | ForEach-Object { $_.Reason += "Algorithm not enabled (in generic config)" } }
+ $Pools | Where-Object { $PoolsConfig.$($_.BaseName).Algorithm -like "+*" } | Where-Object { "+$($_.Algorithm)" -notin $PoolsConfig.$($_.BaseName).Algorithm } | ForEach-Object { $_.Reason += "Algorithm not enabled (``-$($_.Algorithm)``in $($_.BaseName) pool config)" }
+ # Region exclusions
+ $Pools | Where-Object { $PoolsConfig.$($_.BaseName).ExcludeRegion -and $_.Region -in @($PoolsConfig.$($_.BaseName).ExcludeRegion) } | ForEach-Object { $_.Reason += "Region excluded (``$($_.Region)`` in $($_.BaseName) pool config)" }
+ # MinWorkers
+ $Pools | Where-Object { $null -ne $_.Workers -and $_.Workers -lt $PoolsConfig.$($_.BaseName).MinWorker } | ForEach-Object { $_.Reason += "Not enough workers at pool (MinWorker ``$($PoolsConfig.$($_.BaseName).MinWorker)`` in $($_.BaseName) pool config)" }
+ $Pools | Where-Object { $null -ne $_.Workers -and $_.Workers -lt $Config.MinWorker } | ForEach-Object { $_.Reason += "Not enough workers at pool (MinWorker ``$($Config.MinWorker)`` in generic config)" }
+ # Update pools last used, required for BalancesKeepAlive
+ If ($Variables.PoolsLastUsed) { $Variables.PoolsLastUsed | Get-SortedObject | ConvertTo-Json | Out-File -FilePath ".\Data\PoolsLastUsed.json" -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue}
+
+ # Apply watchdog to pools
+ If ($Config.Watchdog) {
+ $Pools | Where-Object Available -EQ $true | Group-Object -Property Name | ForEach-Object {
+ # Suspend pool if > 50% of all algorithms@pool failed
+ $PoolName = $_.Name
+ $WatchdogCount = ($Variables.WatchdogCount, ($Variables.WatchdogCount * $_.Group.Count / 2), (($Variables.Miners | Where-Object Best | Where-Object { $_.WorkersRunning.Pool.Name -eq $PoolName }).count) | Measure-Object -Maximum).Maximum
+ If ($PoolsToSuspend = $_.Group | Where-Object { @($Variables.WatchdogTimers | Where-Object PoolName -EQ $PoolName | Where-Object Kicked -LT $Variables.Timer).Count -gt $WatchdogCount }) {
+ $PoolsToSuspend | ForEach-Object { $_.Reason += "Pool suspended by watchdog" }
+ Write-Message -Level Warn "Pool '$($_.Name)' is suspended by watchdog until $((($Variables.WatchdogTimers | Where-Object PoolName -EQ $_.Name | Where-Object Kicked -LT $Variables.Timer).Kicked | Sort-Object | Select-Object -First 1).AddSeconds($Variables.WatchdogReset).ToLocalTime().ToString("T"))."
+ }
+ }
+ $Pools | Where-Object Available -EQ $true | Group-Object -Property Algorithm, Name | ForEach-Object {
+ # Suspend algorithm@pool if > 50% of all possible miners for algorithm failed
+ $WatchdogCount = ($Variables.WatchdogCount, (($Variables.Miners | Where-Object Algorithm -contains $_.Group[0].Algorithm).Count / 2) | Measure-Object -Maximum).Maximum + 1
+ If ($PoolsToSuspend = $_.Group | Where-Object { @($Variables.WatchdogTimers | Where-Object Algorithm -EQ $_.Algorithm | Where-Object PoolName -EQ $_.Name | Where-Object Kicked -LT $Variables.Timer).Count -gt $WatchdogCount }) {
+ $PoolsToSuspend | ForEach-Object { $_.Reason += "Algorithm@Pool suspended by watchdog" }
+ Write-Message -Level Warn "Algorithm@Pool '$($_.Group[0].Algorithm)@$($_.Group[0].Name)' is suspended by watchdog until $((($Variables.WatchdogTimers | Where-Object Algorithm -EQ $_.Group[0].Algorithm | Where-Object PoolName -EQ $_.Group[0].Name | Where-Object Kicked -LT $Variables.Timer).Kicked | Sort-Object | Select-Object -First 1).AddSeconds($Variables.WatchdogReset).ToLocalTime().ToString("T"))."
+ }
+ }
+ Remove-Variable PoolName, PoolsToSuspend, WatchdogCount -ErrorAction Ignore
+ }
+
+ # Make pools unavailable
+ $Pools | Where-Object Reason | ForEach-Object { $_.Available = $false }
+
+ # Filter pools on miner set
+ If ($Config.MinerSet -lt 2) {
+ $Pools | Where-Object { $Variables.UnprofitableAlgorithms.($_.Algorithm) -eq 1 } | ForEach-Object { $_.Reason += "Unprofitable Primary Algorithm" }
+ $Pools | Where-Object { $Variables.UnprofitableAlgorithms.($_.Algorithm) -eq 2 } | ForEach-Object { $_.Reason += "Unprofitable Secondary Algorithm" }
+ }
+
+ If ($Variables.Pools.Count -gt 0) {
+ Write-Message -Level Info "Had $($Variables.PoolsCount) pool$(If ($Variables.PoolsCount -ne 1) { "s" }), found new $($Variables.AddedPools.Count) pool$(If ($Variables.AddedPools.Count -ne 1) { "s" }), updated $($Variables.UpdatedPools.Count) pool$(If ($Variables.UpdatedPools.Count -ne 1) { "s" }), filtered out $(@($Pools | Where-Object Available -NE $true).Count) pool$(If (@($Pools | Where-Object Available -NE $true).Count -ne 1) { "s" }). $(@($Pools | Where-Object Available -EQ $true).Count) available pool$(If (@($Pools | Where-Object Available -EQ $true).Count -ne 1) { "s" }) remain$(If (@($Pools | Where-Object Available -EQ $true).Count -eq 1) { "s" })."
+ }
+ Else {
+ Write-Message -Level Info "Found $($Variables.NewPools.Count) pool$(If ($NewPools.Count -ne 1) { "s" }), filtered out $(@($Pools | Where-Object Available -NE $true).Count) pool$(If (@($Pools | Where-Object Available -NE $true).Count -ne 1) { "s" }). $(@($Pools | Where-Object Available -EQ $true).Count) available pool$(If (@($Pools | Where-Object Available -EQ $true).Count -ne 1) { "s" }) remain$(If (@($Pools | Where-Object Available -EQ $true).Count -eq 1) { "s" })."
+ }
+
+ # Keep pool balances alive; force mining at pool even if it is not the best for the algo
+ If ($Config.BalancesKeepAlive -and $Variables.BalancesTrackerRunspace -and $Variables.PoolsLastEarnings.Count -gt 0) {
+ $PoolNamesToKeepBalancesAlive = @()
+ ForEach ($Pool in @($Pools | Where-Object Name -notin $Config.BalancesTrackerIgnorePool | Sort-Object Name -Unique)) {
+
+ $PoolName = Get-PoolBaseName $Pool.Name
+
+ $BalancesKeepAliveDays = $PoolsConfig.$PoolName.BalancesKeepAlive
+
+ If ($BalancesKeepAliveDays -gt 0 -and (-not $Variables.PoolsLastEarnings.$PoolName -or (((Get-Date).ToUniversalTime() - $Variables.PoolsLastEarnings.$PoolName).Days) -ge $BalancesKeepAliveDays)) {
+ If (-not $Variables.PoolsLastUsed.$PoolName) {
+ $PoolNamesToKeepBalancesAlive += $Pool.Name
+ Write-Message -Level Warn "Pool ($PoolName) prioritized to avoid forfeiting balance (pool would clear balance after $($BalancesKeepAliveDays) days of inactivity)."
+ }
+ ElseIf (((Get-Date).ToUniversalTime() - $Variables.PoolsLastUsed.$PoolName).Days -ge $BalancesKeepAliveDays - 1) {
+ $PoolNamesToKeepBalancesAlive += $Pool.Name
+ Write-Message -Level Warn "Pool ($PoolName) prioritized to avoid forfeiting balance (pool would clear balance tomorrow)."
+ }
+ }
+ }
+ If ($PoolNamesToKeepBalancesAlive) {
+ $Pools | ForEach-Object {
+ If ($_.Name -in $PoolNamesToKeepBalancesAlive) { $_.Available = $true; $_.Reason = "Prioritized by BalancesKeepAlive" }
+ Else { $_.Reason += "BalancesKeepAlive prioritizes other pools" }
+ }
+ }
+ Remove-Variable BalancesKeepAliveDays, Pool, PoolName -ErrorAction Ignore
+ }
+
+ # Sort best pools
+ [Pool[]]$SortedAvailablePools = $Pools | Where-Object Available -EQ $true | Sort-Object { $_.Name -notin $PoolNamesToKeepBalancesAlive }, { - $_.StablePrice * $_.Accuracy }, { $Variables.Regions.($Config.Region).IndexOf($_.Region) }
+ (($SortedAvailablePools).Algorithm | Select-Object -Unique) | ForEach-Object {
+ $SortedAvailablePools | Where-Object Algorithm -EQ $_ | Select-Object -First 1 | ForEach-Object { $_.Best = $true }
+ }
+ }
+
+ # Update data in API
+ $Variables.Pools = $Pools
+ Remove-Variable ComparePools, Pools, PoolNames, PoolNamesToKeepBalancesAlive, PoolsConfig, SortedAvailablePools -ErrorAction Ignore
+ }
+
+ # Faster shutdown
+ If ($Variables.NewMiningStatus -ne "Running" -or $Variables.IdleRunspace.NewMiningStatus -eq "Idle") { Break }
+
+ # Put here in case the port range has changed
+ Initialize-API
+
+ # Tuning parameters require local admin rights
+ $Variables.UseMinerTweaks = ($Variables.IsLocalAdmin -and $Config.UseMinerTweaks)
+
+ If ($Variables.Pools) {
+ # For legacy miners
+ $MinerPools = [PSCustomObject]@{ }
+ $PoolsPrimaryAlgorithm = [PSCustomObject]@{ }
+ $PoolsSecondaryAlgorithm = [PSCustomObject]@{ }
+ $Variables.Pools | Where-Object Best -EQ $true | Sort-Object Algorithm | ForEach-Object {
+ $MinerPools | Add-Member $_.Algorithm $_
+ If ($_.Reason -ne "Unprofitable Primary Algorithm") { $PoolsPrimaryAlgorithm | Add-Member $_.Algorithm $_ } # Allow unprofitable algos for primary algorithm
+ If ($_.Reason -ne "Unprofitable Secondary Algorithm") { $PoolsSecondaryAlgorithm | Add-Member $_.Algorithm $_ } # Allow unprofitable algos for secondary algorithm
+ }
+
+ # Get new miners
+ If (-not ($Variables.Pools -and $Variables.Miners)) { $Variables.Summary = "Loading miners..." }
+ Write-Message -Level Verbose "Loading miners..."
+ $NewMiners_Jobs = @(
+ Get-ChildItemContent ".\Miners" -Parameters @{ Pools = $PoolsPrimaryAlgorithm; PoolsSecondaryAlgorithm = $PoolsSecondaryAlgorithm; Config = $Config; Variables = $Variables } -Threaded -Priority $(If ($Variables.Miners | Where-Object { $_.Status -eq [MinerStatus]::Running } | Where-Object { $_.DeviceName -like "CPU#*" }) { "Normal" })
+ If (Test-Path -Path ".\CustomMiners\.ps1" -PathType Leaf) { Get-ChildItemContent ".\CustomMiners" -Parameters @{ Pools = $PoolsPrimaryAlgorithm; PoolsSecondaryAlgorithm = $PoolsSecondaryAlgorithm; Config = $Config; Variables = $Variables } -Threaded -Priority $(If ($Miners | Where-Object { $_.Status -eq [MinerStatus]::Running } | Where-Object { $_.DeviceName -like "CPU#*" }) { "Normal" }) }
+ )
+ Remove-Variable PoolsPrimaryAlgorithm, PoolsSecondaryAlgorithm
+ }
+
+ # Ensure we get the hashrate for running miners prior looking for best miner
+ $Miners = $Variables.Miners
+ ForEach ($Miner in ($Miners | Where-Object Best)) {
+ If ($Miner.DataReaderJob.HasMoreData) {
+ # Reduce data to MinDataSamples * 5
+ $Miner.Data = @($Miner.Data | Select-Object -Last ($Miner.MinDataSamples * 5))
+ $Miner.Data += @($Miner.DataReaderJob | Receive-Job | Select-Object -Property Date, Hashrate, Shares, PowerUsage)
+ }
+
+ If ($Miner.Status -eq [MinerStatus]::Running) {
+ If ($Miner.GetStatus() -eq [MinerStatus]::Running) {
+ If ($Config.Watchdog) {
+ ForEach ($Worker in $Miner.WorkersRunning) {
+ If ($WatchdogTimer = $Variables.WatchdogTimers | Where-Object MinerName -EQ $Miner.Name | Where-Object PoolName -EQ $Worker.Pool.Name | Where-Object PoolRegion -EQ $Worker.Pool.Region | Where-Object Algorithm -EQ $Worker.Pool.Algorithm | Sort-Object Kicked | Select-Object -Last 1) {
+ #Update watchdog timers
+ $WatchdogTimer.Kicked = (Get-Date).ToUniversalTime()
+ }
+ Else {
+ # Create watchdog timer
+ $Variables.WatchdogTimers += [PSCustomObject]@{
+ MinerName = $Miner.Name
+ MinerBaseName = $Miner.BaseName
+ MinerVersion = $Miner.Version
+ PoolName = $Worker.Pool.Name
+ PoolRegion = $Worker.Pool.Region
+ Algorithm = $Worker.Pool.Algorithm
+ DeviceName = [String[]]$Miner.DeviceName
+ Kicked = (Get-Date).ToUniversalTime()
+ }
+ }
+ }
+ }
+ If ($Config.BadShareRatioThreshold -gt 0) {
+ $Miner.WorkersRunning.Pool.Algorithm | ForEach-Object {
+ $LastSharesData = ($Miner.Data | Select-Object -Last 1).Shares
+ If ($LastSharesData.$_ -and $LastSharesData.$_[1] -gt 0 -and $LastSharesData.$_[2] -gt [Int](1 / $Config.BadShareRatioThreshold) -and $LastSharesData.$_[1] / $LastSharesData.$_[2] -gt $Config.BadShareRatioThreshold) {
+ $Miner.StatusMessage = "Miner '$($Miner.Name) $($Miner.Info)' stopped. Reason: Too many bad shares (Shares Total = $($LastSharesData.$_[2]), Rejected = $($LastSharesData.$_[1]))."
+ $Miner.Data = @() # Clear data because it may be incorrect caused by miner problem
+ $Miner.SetStatus([MinerStatus]::Failed)
+ }
+ }
+ }
+ }
+ Else {
+ $Miner.StatusMessage = "Miner '$($Miner.Name) $($Miner.Info)' exited unexpectedly."
+ $Miner.SetStatus([MinerStatus]::Failed)
+ }
+ }
+
+ $Miner.Speed_Live = @()
+ $PowerUsage = [Double]::NaN
+ If ($Miner.Data.Count) {
+ # Collect hashrate from miner, returns an array of two values (safe, unsafe)
+ $Miner_Speeds = [Hashtable]@{ }
+ ForEach ($Algorithm in $Miner.Algorithm) {
+ $CollectedHashrate = $Miner.CollectHashrate($Algorithm, (-not $Miner.Benchmark -and $Miner.Data.Count -lt $Miner.MinDataSamples))
+ $Miner.Speed_Live += [Double]($CollectedHashrate[1])
+ $Miner_Speeds.$Algorithm = [Double]($CollectedHashrate[0])
+ }
+ If ($Miner.ReadPowerUsage) {
+ # Collect power usage from miner, returns an array of two values (safe, unsafe)
+ $CollectedPowerUsage = $Miner.CollectPowerUsage(-not $Miner.MeasurePowerUsage -and $Miner.Data.Count -lt $Miner.MinDataSamples)
+ $Miner.PowerUsage_Live = [Double]($CollectedPowerUsage[1])
+ $PowerUsage = [Double]($CollectedPowerUsage[0])
+ }
+ }
+
+ # Do not save data if stat just got removed (Miner.Activated < 1, set by API)
+ If ($Miner.Activated -gt 0) {
+ # We don't want to store hashrates if we have less than $MinDataSamples
+ If ($Miner.Data.Count -ge $Miner.MinDataSamples -or $Miner.Activated -gt $Variables.WatchdogCount) {
+ $Miner.StatEnd = (Get-Date).ToUniversalTime()
+ $Stat_Span = [TimeSpan]($Miner.StatEnd - $Miner.StatStart)
+
+ ForEach ($Worker in $Miner.WorkersRunning) {
+ $Algorithm = $Worker.Pool.Algorithm
+ $Factor = 1
+ $Stat_Name = "$($Miner.Name)_$($Algorithm)_Hashrate"
+ $LastSharesData = ($Miner.Data | Select-Object -Last 1).Shares
+ If ($Miner.Data.Count -gt $Miner.MinDataSamples -and -not $Miner.Benchmark -and $Config.SubtractBadShares -and $LastSharesData -and $LastSharesData.$Algorithm[1] -gt 0) { # Need $Miner.MinDataSamples shares before adjusting hash rate
+ $Factor = $(1 - $LastSharesData.$Algorithm[1] / $LastSharesData.$Algorithm[2])
+ $Miner_Speeds.$Algorithm *= $Factor
+ }
+ $Stat = Set-Stat -Name $Stat_Name -Value $Miner_Speeds.$Algorithm -Duration $Stat_Span -FaultDetection ($Miner.Data.Count -ge $Miner.MinDataSamples) -ToleranceExceeded ($Variables.WatchdogCount + 1)
+ If ($Stat.Updated -gt $Miner.StatStart) {
+ Write-Message -Level Info "Saved hash rate for '$($Stat_Name -replace '_Hashrate$')': $(($Miner_Speeds.$Algorithm | ConvertTo-Hash) -replace ' ')$(If ($Factor -le 0.999) { " (adjusted by factor $($Factor.ToString('N3')) [Shares total: $($LastSharesData.$Algorithm[2]), rejected: $($LastSharesData.$Algorithm[1])])" })$(If ($Stat.Duration -eq $Stat_Span) { " [Benchmark done]" })."
+ $Miner.StatStart = $Miner.StatEnd
+ $Variables.PoolsLastUsed.(Get-PoolBaseName $Worker.Pool.Name) = $Stat.Updated # most likely this will count at the pool to keep balances alive
+ }
+ ElseIf ($Miner_Speeds.$Algorithm -gt 0 -and $Miner.Status -eq [MinerStatus]::Running -and $Stat.Week -and ($Miner_Speeds.$Algorithm -gt $Stat.Week * 2 -or $Miner_Speeds.$Algorithm -lt $Stat.Week / 2)) { # Stop miner if new value is outside ±200% of current value
+ $Miner.StatusMessage = "$($Miner.Name) $($Miner.Info): Reported hashrate is unreal ($($Algorithm): $(($Miner_Speeds.$Algorithm | ConvertTo-Hash) -replace ' ') is not within ±200% of stored value of $(($Stat.Week | ConvertTo-Hash) -replace ' '))."
+ $Miner.SetStatus([MinerStatus]::Failed)
+ }
+ }
+ }
+ If ($Miner.ReadPowerUsage -eq $true -and ($Stat.Updated -gt $Miner.StatStart -or $Miner.Activatd -gt $Variables.WatchdogCount)) {
+ If ([Double]::IsNaN($PowerUsage)) { $PowerUsage = 0 }
+ $Stat_Name = "$($Miner.Name)$(If ($Miner.Workers.Count -eq 1) { "_$($Miner.Workers.Pool.Algorithm | Select-Object -First 1)" })_PowerUsage"
+ $Stat = Set-Stat -Name $Stat_Name -Value $PowerUsage -Duration $Stat_Span -FaultDetection ($Miner.Data.Count -gt $Miner.MinDataSamples) -ToleranceExceeded ($Variables.WatchdogCount + 1)
+ If ($Stat.Updated -gt $Miner.StatStart) {
+ Write-Message -Level Info "Saved power usage for '$($Stat_Name -replace '_PowerUsage$')': $($Stat.Live.ToString("N2"))W$(If ($Stat.Duration -eq $Stat_Span) { " [Power usage measurement done]" })."
+ }
+ ElseIf ($PowerUsage -gt 0 -and $Miner.Status -eq [MinerStatus]::Running -and $Stat.Week -and ($PowerUsage -gt $Stat.Week * 2 -or $PowerUsage -lt $Stat.Week / 2)) {
+ # Stop miner if new value is outside ±200% of current value
+ $Miner.StatusMessage = "$($Miner.Name) $($Miner.Info): Reported power usage is unreal ($($PowerUsage.ToString("N2"))W is not within ±200% of stored value of $(([Double]$Stat.Week).ToString("N2"))W)."
+ $Miner.SetStatus([MinerStatus]::Failed)
+ }
+ }
+ Remove-Variable Factor, LastSharesData, Stat_Name, Stat_Span, Stat -ErrorAction Ignore
+ }
+ }
+ Remove-Variable Algorithm, CollectedHashrate, CollectPowerUsage, Miner, Miner_Speeds, PowerUsage, WatchdogTimer -ErrorAction Ignore
+
+ # Faster shutdown
+ If ($Variables.NewMiningStatus -ne "Running" -or $Variables.IdleRunspace.NewMiningStatus -eq "Idle") { Break }
+
+ # Retrieve collected miner objects
+ $NewMiners = @(
+ $NewMiners_Jobs | ForEach-Object { $_ | Get-Job -ErrorAction Ignore | Wait-Job -Timeout 60 | Receive-Job } | Where-Object { $_.Content.API } | ForEach-Object {
+ [PSCustomObject]@{
+ Name = [String]$_.Content.Name
+ BaseName = [String]($_.Content.Name -split '-' | Select-Object -First 1)
+ Version = [String]($_.Content.Name -split '-' | Select-Object -Index 1)
+ Path = [String]$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($_.Content.Path)
+ Algorithm = [String[]]$_.Content.Algorithm
+ Pool = [String[]]@(ForEach ($Algorithm in $_.Content.Algorithm) { $MinerPools.$Algorithm.Name })
+ Workers = [Worker[]]@(ForEach ($Algorithm in $_.Content.Algorithm) { @{ Pool = $MinerPools.$Algorithm; Fee = If ($Config.IgnoreMinerFee) { 0 } Else { [Double]($_.Content.Fee | Select-Object -Index $_.Content.Algorithm.IndexOf($Algorithm)) } } })
+ Arguments = [String]$_.Content.Arguments
+ DeviceName = [String[]]$_.Content.DeviceName
+ Devices = [Device[]]($Variables.Devices | Where-Object Name -In $_.Content.DeviceName)
+ Type = [String]$_.Content.Type
+ Port = [UInt16]$_.Content.Port
+ URI = [String]$_.Content.URI
+ EnvVars = [String[]]$_.Content.EnvVars
+ WarmupTimes = [Int[]]$_.Content.WarmupTimes
+ MinerUri = [String]$_.Content.MinerUri
+ LogFile = [String]$_.Content.LogFile
+ API = [String]$_.Content.API
+ } -as "$($_.Content.API)"
+ }
+ )
+ $NewMiners_Jobs | ForEach-Object { $_ | Remove-Job -ErrorAction Ignore -Force }
+ Remove-Variable Algorithm, MinerPools, NewMiners_Jobs -ErrorAction Ignore
+
+ $CompareMiners = Compare-Object -PassThru @($Miners | Select-Object) @($NewMiners | Select-Object) -Property Arguments, Name, Pool -IncludeEqual
+ # Remove gone miners
+ $Miners = $CompareMiners | Where-Object SideIndicator -NE "<=" | ForEach-Object { $_.PSObject.Properties.Remove('SideIndicator'); $_ }
+
+ If ($Miners) {
+ $Miners | Select-Object | ForEach-Object {
+ $_.Restart = $false
+ $_.KeepRunning = $_.Status -eq [MinerStatus]::Running -and -not $_.Benchmark -and -not $_.MeasurePowerUsage -and $_.BeginTime.AddSeconds($Config.Interval * ($Config.MinInterval -1)) -gt $Variables.Timer -and -not $Variables.DonateRandom # Minimum numbers of full cycles not yet reached
+
+ If ($Miner = Compare-Object -PassThru @($NewMiners | Select-Object) @($_ | Select-Object) -Property Arguments, Name, Pool -ExcludeDifferent | Select-Object -ExcludeProperty SideIndicator) {
+ # Update existing miners
+ If (-not $_.KeepRunning) {
+ $_.Restart = $_.Arguments -ne $Miner.Arguments
+ }
+ If ($_.Restart) {
+ $_.Arguments = $Miner.Arguments
+ $_.Devices = $Miner.Devices
+ $_.DeviceName = $Miner.DeviceName
+ $_.Port = $Miner.Port
+ $_.Workers = $Miner.Workers
+ }
+ $_.MinerUri = $Miner.MinerUri
+ $_.WarmupTimes = $Miner.WarmupTimes
+ }
+
+ $_.ReadPowerUsage = [Boolean]($_.Devices.ReadPowerUsage -notcontains $false)
+ $_.Refresh($Variables.PowerCostBTCperW, $Variables.CalculatePowerCost) # Needs to be done after ReadPowerUsage evaluation
+ $_.CommandLine = $_.GetCommandLine().Replace("$(Convert-Path '.\')\", '')
+ $_.MinDataSamples = [Int]($Config.MinDataSamples * (($_.Algorithm | ForEach-Object { $Config.MinDataSamplesAlgoMultiplier.$_ }), 1 | Measure-Object -Maximum).Maximum)
+ $_.ProcessPriority = If ($_.Type -eq "CPU") { $Config.CPUMinerProcessPriority } Else { $Config.GPUMinerProcessPriority }
+ $_.WindowStyle = If ($_.Benchmark -eq $true -and $Config.MinerWindowStyleNormalWhenBenchmarking -eq $true) { "normal" } Else { $Config.MinerWindowStyle }
+ $_.PSObject.Properties.Remove("SideIndicator")
+ }
+ Remove-Variable DataCollectInterval, Miner, NewMiners, ReadPowerUsage -ErrorAction Ignore
+
+ # Filter miners
+ $Miners | Where-Object Disabled -EQ $true | ForEach-Object { $_.Reason += "Disabled by user" }
+ $Miners | Where-Object { $_.Workers[0].Speed -EQ 0 } | ForEach-Object { $_.Reason += "0 H/s Stat file" } # Allow 0 hashrate for secondary algorithm
+ If ($Config.ExcludeMinerName.Count) { $Miners | Where-Object { (Compare-Object $Config.ExcludeMinerName @($_.BaseName, "$($_.BaseName)-$($_.Version)", $_.Name | Select-Object -Unique) -IncludeEqual -ExcludeDifferent | Measure-Object).Count -gt 0 } | ForEach-Object { $_.Reason += "ExcludeMinerName ($($Config.ExcludeMinerName -Join '; '))" } }
+ If ($Config.ExcludeDeviceName.Count) { $Miners | Where-Object { (Compare-Object $Config.ExcludeDeviceName @($_.DeviceName | Select-Object) -IncludeEqual -ExcludeDifferent | Measure-Object).Count -gt 0 } | ForEach-Object { $_.Reason += "ExcludeDeviceName ($($Config.ExcludeDeviceName -Join '; '))" }}
+ $Miners | Where-Object Available -EQ $true | Where-Object Earning -EQ 0 | ForEach-Object { $_.Reason += "Earning -eq 0" }
+ If ($Config.DisableMinersWithFee) { $Miners | Where-Object Fee -GT 0 | ForEach-Object { $_.Reason += "Config.DisableMinersWithFee" } }
+ If ($Config.DisableDualAlgoMining) { $Miners | Where-Object Workers.Count -EQ 2 | ForEach-Object { $_.Reason += "Config.DisableDualAlgoMining" } }
+ If ($Config.DisableSingleAlgoMining) { $Miners | Where-Object Workers.Count -EQ 1 | ForEach-Object { $_.Reason += "Config.DisableSingleAlgoMining" } }
+
+ $Variables.MinersNeedingBenchmark = @($Miners | Where-Object Disabled -NE $true | Where-Object Benchmark -EQ $true)
+ $Variables.MinersNeedingPowerUsageMeasurement = @($Miners | Where-Object Disabled -NE $true | Where-Object MeasurePowerUsage -EQ $true)
+
+ # Detect miners with unreal earning (> x times higher than average of the next best 10% or at least 5 miners)
+ If ($Config.UnrealMinerEarningFactor -gt 1) {
+ $Miners | Where-Object { -not $_.Reason} | Group-Object { $_.DeviceName } | ForEach-Object {
+ If ($ReasonableEarning = [Double]($_.Group | Sort-Object -Descending Earning | Select-Object -Skip 1 -First (5, [Int]($_.Group.Count / 10) | Measure-Object -Maximum).Maximum | Measure-Object Earning -Average).Average * $Config.UnrealMinerEarningFactor) {
+ $_.Group | Where-Object Earning -GT $ReasonableEarning | ForEach-Object { $_.Reason += "Unreal profit data (-gt $($Config.UnrealMinerEarningFactor)x higher than the next best miners available miners of the same device(s))" }
+ }
+ }
+ }
+ Remove-Variable ReasonableEarning -ErrorAction Ignore
+
+ $Variables.MinersMissingBinary = @()
+ $Miners | Where-Object Available -EQ $true | Where-Object { -not (Test-Path $_.Path -Type Leaf -ErrorAction Ignore) } | ForEach-Object {
+ $_.Reason += "Binary missing"
+ $Variables.MinersMissingBinary += $_
+ }
+
+ # Apply watchdog to miners
+ If ($Config.Watchdog) {
+ $Miners | Where-Object Available -EQ $true | Group-Object -Property { "$($_.BaseName)-$($_.Version)" } | ForEach-Object {
+ # Suspend miner if > 50% of all available algorithms failed
+ $WatchdogMinerCount = ($Variables.WatchdogCount, [Math]::Ceiling($Variables.WatchdogCount * $_.Group.Count / 2) | Measure-Object -Maximum).Maximum
+ If ($MinersToSuspend = @($_.Group | Where-Object { @($Variables.WatchdogTimers | Where-Object MinerBaseName -EQ $_.BaseName | Where-Object MinerVersion -EQ $_.Version | Where-Object Kicked -LT $Variables.Timer).Count -gt $WatchdogMinerCount })) {
+ $MinersToSuspend | ForEach-Object {
+ $_.Data = @() # Clear data because it may be incorrect caused by miner problem
+ $_.Reason += "Miner suspended by watchdog (all algorithms)"
+ }
+ Write-Message -Level Warn "Miner '$($_.Group[0].BaseName)-$($_.Group[0].Version) [all algorithms]' is suspended by watchdog until $((($Variables.WatchdogTimers | Where-Object MinerBaseName -EQ $_.Group[0].BaseName | Where-Object MinerVersion -EQ $_.Group[0].Version | Where-Object Kicked -LT $Variables.Timer).Kicked | Sort-Object | Select-Object -Last 1).AddSeconds($Variables.WatchdogReset).ToLocalTime().ToString("T"))."
+ }
+ Remove-Variable MinersToSuspend, WatchdogMinerCount -ErrorAction Ignore
+ }
+ $Miners | Where-Object Available -EQ $true | Where-Object { @($Variables.WatchdogTimers | Where-Object MinerName -EQ $_.Name | Where-Object DeviceName -EQ $_.DeviceName | Where-Object Algorithm -EQ $_.Algorithm | Where-Object Kicked -LT $Variables.Timer).Count -ge $Variables.WatchdogCount } | ForEach-Object {
+ $_.Data = @() # Clear data because it may be incorrect caused by miner problem
+ $_.Reason += "Miner suspended by watchdog (Algorithm $($_.Algorithm))"
+ Write-Message -Level Warn "Miner '$($_.Name) [$($_.Algorithm)]' is suspended by watchdog until $((($Variables.WatchdogTimers | Where-Object MinerName -EQ $_.Name | Where-Object DeviceName -EQ $_.DeviceName | Where-Object Algorithm -EQ $_.Algorithm | Where-Object Kicked -LT $Variables.Timer).Kicked | Sort-Object | Select-Object -Last 1).AddSeconds($Variables.WatchdogReset).ToLocalTime().ToString("T"))."
+ }
+ }
+
+ $Miners | Where-Object Reason | ForEach-Object { $_.Available = $false }
+
+ Write-Message -Level Info "Found $($Miners.Count) miner$(If ($Miners.Count -ne 1) { "s" }), $(($Miners | Where-Object Available -EQ $true).Count) available miner$(If (($Miners | Where-Object Available -EQ $true).Count -ne 1) { "s" }) remain$(If (($Miners | Where-Object Available -EQ $true).Count -eq 1) { "s" }) (filtered out $(($Miners | Where-Object Available -NE $true).Count) miner$(If (($Miners | Where-Object Available -NE $true).Count -ne 1) { "s" }))."
+
+ If ($Variables.MinersMissingBinary) {
+ # Download miner binaries
+ If ($Variables.Downloader.State -ne "Running") {
+ Write-Message -Level Info "Some miners binaries are missing, starting downloader..."
+ $Downloader_Parameters = @{
+ Config = $Config
+ DownloadList = @($Variables.MinersMissingBinary | Select-Object URI, Path, @{ Name = "Searchable"; Expression = { $Miner = $_; @($Miners | Where-Object { (Split-Path $_.Path -Leaf) -eq (Split-Path $Miner.Path -Leaf) }).Count -eq 0 } }) | Select-Object * -Unique
+ Variables = $Variables
+ }
+ $Variables.Downloader = Start-ThreadJob -ThrottleLimit 99 -Name Downloader -InitializationScript ([scriptblock]::Create("Set-Location '$($Variables.MainPath)'")) -ArgumentList $Downloader_Parameters -FilePath ".\Includes\Downloader.ps1"
+ Remove-Variable Downloader_Parameters
+ }
+ ElseIf (-not ($Miners | Where-Object Available -EQ $true)) {
+ Write-Message -Level Info "Waiting 30 seconds for downloader to install binaries..."
+ }
+ }
+
+ # Open firewall ports for all miners
+ If ($Config.OpenFirewallPorts) {
+ If (Get-Command "Get-MpPreference" -ErrorAction Ignore) {
+ $ProgressPreferenceBackup = $ProgressPreference
+ $ProgressPreference = "SilentlyContinue"
+ If ((Get-Command "Get-MpComputerStatus" -ErrorAction Ignore) -and (Get-MpComputerStatus -ErrorAction Ignore)) {
+ If (Get-Command "Get-NetFirewallRule" -ErrorAction Ignore) {
+ $MinerFirewallRules = @((Get-NetFirewallApplicationFilter).Program)
+ If (Compare-Object $MinerFirewallRules @($Miners | Select-Object -ExpandProperty Path -Unique) | Where-Object SideIndicator -EQ "=>") {
+ Start-Process "pwsh" ("-Command Import-Module NetSecurity; ('$(Compare-Object $MinerFirewallRules @($Miners | Select-Object -ExpandProperty Path -Unique) | Where-Object SideIndicator -EQ '=>' | Select-Object -ExpandProperty InputObject | ConvertTo-Json -Compress)' | ConvertFrom-Json) | ForEach-Object { New-NetFirewallRule -DisplayName (Split-Path `$_ -leaf) -Program `$_ -Description 'Inbound rule added by $($Variables.Branding.ProductLabel) $($Variables.Branding.Version) on $((Get-Date).ToString())' -Group 'Cryptocurrency Miner' }" -replace '"', '\"') -Verb runAs
+ }
+ Remove-Variable MinerFirewallRules
+ }
+ }
+ $ProgressPreference = $ProgressPreferenceBackup
+ Remove-Variable ProgressPreferenceBackup
+ }
+ }
+ }
+
+ If ($Miners | Where-Object Available -EQ $true) {
+ Write-Message -Level Info "Selecting best miner$(If (@($Variables.EnabledDevices.Model | Select-Object -Unique).Count -gt 1) { "s" }) based on$(If ($Variables.CalculatePowerCost) { " profit (power cost $($Config.Currency) $($Variables.PowerPricekWh)/kW⋅h)" } Else { " earning" })..."
+
+ If (($Miners | Where-Object Available -EQ $true) -eq 1) {
+ $Variables.BestMiners_Combo = $Variables.BestMiners = $Variables.MostProfitableMiners = $Miners
+ }
+ Else {
+ If ($Variables.CalculatePowerCost -and -not $Config.IgnorePowerCost) { $SortBy = "Profit" } Else { $SortBy = "Earning" }
+
+ # Add running miner bonus
+ $Miners | Where-Object { $_.Status -eq [MinerStatus]::Running } | ForEach-Object { $_."$($SortBy)_Bias" *= (1 + $Config.MinerSwitchingThreshold / 100) }
+
+ # Hack: temporarily make all bias positive, BestMiners_Combos(_Comparison) produces wrong sort order when earnings or profits are negative
+ $SmallestBias = [Double][Math]::Abs((($Miners | Where-Object Available -EQ $true | Where-Object { -not [Double]::IsNaN($_."$($SortBy)_Bias") })."$($SortBy)_Bias" | Measure-Object -Minimum).Minimum) * 2
+ $Miners | ForEach-Object { $_."$($SortBy)_Bias" += $SmallestBias }
+
+ # Get most best miner combination i.e. AMD+NVIDIA+CPU
+ $Variables.MostProfitableMiners = @($Miners | Where-Object Available -EQ $true | Group-Object { [String]$_.DeviceName }, { [String]$_.Algorithm } | ForEach-Object { $_.Group | Sort-Object -Descending -Property Benchmark, MeasurePowerUsage, KeepRunning, Prioritize, "$($SortBy)_Bias", Activated, @{ Expression = { $_.WarmupTimes[0] }; Descending = $false }, Name | Select-Object -First 1 | ForEach-Object { $_.MostProfitable = $true; $_ } })
+ $Variables.BestMiners = @($Variables.MostProfitableMiners | Group-Object { [String]$_.DeviceName } | ForEach-Object { $_.Group | Sort-Object -Descending -Property Benchmark, MeasurePowerUsage, KeepRunning, Prioritize, "$($SortBy)_Bias", Activated, @{ Expression = { $_.WarmupTimes[0] }; Descending = $false }, Name | Select-Object -First 1 })
+ $Variables.Miners_Device_Combos = @(Get-Combination @($Variables.BestMiners | Select-Object DeviceName -Unique) | Where-Object { (Compare-Object ($_.Combination | Select-Object -ExpandProperty DeviceName -Unique) ($_.Combination | Select-Object -ExpandProperty DeviceName) | Measure-Object).Count -eq 0 })
+
+ $Variables.BestMiners_Combos = @(
+ $Variables.Miners_Device_Combos | ForEach-Object {
+ $Miner_Device_Combo = $_.Combination
+ [PSCustomObject]@{
+ Combination = $Miner_Device_Combo | ForEach-Object {
+ $Miner_Device_Count = $_.DeviceName.Count
+ [Regex]$Miner_Device_Regex = "^(" + (($_.DeviceName | ForEach-Object { [Regex]::Escape($_) }) -join '|') + ")$"
+ $Variables.BestMiners | Where-Object { ([Array]$_.DeviceName -notmatch $Miner_Device_Regex).Count -eq 0 -and ([Array]$_.DeviceName -match $Miner_Device_Regex).Count -eq $Miner_Device_Count }
+ }
+ }
+ }
+ )
+ $Variables.BestMiners_Combo = @(($Variables.BestMiners_Combos | Sort-Object -Descending { @($_.Combination | Where-Object { [Double]::IsNaN($_.$SortBy) }).Count }, { ($_.Combination | Measure-Object "$($SortBy)_Bias" -Sum).Sum }, { ($_.Combination | Where-Object { $_.$Sortby -ne 0 } | Measure-Object).Count } | Select-Object -First 1).Combination)
+ Remove-Variable Miner_Device_Combo, Miner_Device_Count, Miner_Device_Regex -ErrorAction Ignore
+
+ # Hack part 2: reverse temporarily forced positive bias
+ $Miners | ForEach-Object { $_."$($SortBy)_Bias" -= $SmallestBias }
+
+ # Don't penalize active miners, revert running miner bonus
+ $Miners | Where-Object { $_.Status -eq [MinerStatus]::Running } | ForEach-Object { $_."$($SortBy)_Bias" /= (1 + $Config.MinerSwitchingThreshold / 100) }
+
+ Remove-Variable SmallestBias, SortBy
+ }
+
+ $Variables.MiningEarning = [Double]($Variables.BestMiners_Combo | Measure-Object Earning -Sum).Sum
+ $Variables.MiningProfit = [Double]($Variables.BestMiners_Combo | Measure-Object Profit -Sum).Sum
+ $Variables.MiningPowerCost = [Double]($Variables.BestMiners_Combo | Measure-Object PowerCost -Sum).Sum
+ $Variables.MiningPowerUsage = [Double]($Variables.BestMiners_Combo | Measure-Object PowerUsage -Sum).Sum
+
+ # ProfitabilityThreshold check - OK to run miners?
+ If (-not $Variables.Rates -or -not $Variables.Rates.BTC.($Config.Currency) -or [Double]::IsNaN($Variables.MiningEarning) -or [Double]::IsNaN($Variables.MiningProfit) -or [Double]::IsNaN($Variables.MiningPowerCost) -or ($Variables.MiningEarning - $Variables.MiningPowerCost - $Variables.BasePowerCostBTC) -ge ($Config.ProfitabilityThreshold / $Variables.Rates.BTC.($Config.Currency)) -or $Variables.MinersNeedingBenchmark -or $Variables.MinersNeedingPowerUsageMeasurement) {
+ $Variables.BestMiners_Combo | Select-Object | ForEach-Object { $_.Best = $true }
+ }
+ Else {
+ Write-Message -Level Warn "Mining profit ($($Config.Currency) $(ConvertTo-LocalCurrency -Value ($Variables.MiningEarning - $Variables.MiningPowerCost - $Variables.BasePowerCostBTC) -Rate $Variables.Rates."BTC".($Config.Currency) -Offset 1)) is below the configured threshold of $($Config.Currency) $($Config.ProfitabilityThreshold.ToString("N$((Get-Culture).NumberFormat.CurrencyDecimalDigits)"))/day; mining is suspended until threshold is reached."
+ }
+ }
+ Else {
+ $Variables.MostProfitableMiners = @()
+ $Variables.BestMiners = @()
+ $Variables.Miners_Device_Combos = @()
+ $Variables.BestMiners_Combos = @()
+ $Variables.BestMiners_Combo = @()
+
+ $Variables.MiningEarning = $Variables.MiningProfit = $Variables.MiningPowerCost = $Variables.MiningPowerUsage = [Double]0
+ }
+
+ # Update data in API
+ $Variables.Miners = $Miners
+
+ If ($Variables.Rates."BTC") {
+ $Variables.Summary = ""
+ If ([Double]::IsNaN($Variables.MiningEarning)) {
+ $Variables.Summary += "Earning / day: n/a (Benchmarking: $(($Variables.Miners | Where-Object Available | Where-Object Benchmark).Count) $(If (($Variables.Miners | Where-Object Available | Where-Object Benchmark).Count -eq 1) { "miner" } Else { "miners"}) left)"
+ }
+ ElseIf ($Variables.MiningEarning -gt 0) {
+ $Variables.Summary += "Earning / day: {1:N} {0}" -f $Config.Currency, ($Variables.MiningEarning * $Variables.Rates."BTC".($Config.Currency))
+ }
+
+ If ($Variables.CalculatePowerCost -eq $true) {
+ If ($Variables.Summary -ne "") { $Variables.Summary += " " }
+
+ If ([Double]::IsNaN($Variables.MiningEarning) -or [Double]::IsNaN($Variables.MiningPowerCost)) {
+ $Variables.Summary += "Profit / day: n/a (Measuring: $(($Variables.Miners | Where-Object Available | Where-Object MeasurePowerUsage).Count) $(If (($Variables.Miners | Where-Object Available | Where-Object MeasurePowerUsage).Count -eq 1) { "miner" } Else { "miners"}) left)"
+ }
+ ElseIf ($Variables.MiningPowerUsage -gt 0) {
+ $Variables.Summary += "Profit / day: {1:N} {0}" -f $Config.Currency, (($Variables.MiningProfit - $Variables.BasePowerCostBTC) * $Variables.Rates."BTC".($Config.Currency))
+ }
+ Else {
+ $Variables.Summary += "Profit / day: n/a (no power data)"
+ }
+
+ If ($Variables.BasePowerCostBTC -gt 0) {
+ If ($Variables.Summary -ne "") { $Variables.Summary += " " }
+
+ If ([Double]::IsNaN($Variables.MiningEarning) -or [Double]::IsNaN($Variables.MiningPowerCost)) {
+ $Variables.Summary += "Power Cost / day: n/a (Miner$(If ($Variables.BestMiners_Combo.Count -gt 1) { "s" }): n/a; Base: {1:N} {0} [{2:0}W])" -f $Config.Currency, ($Variables.BasePowerCostBTC * $Variables.Rates."BTC".($Config.Currency)), $Config.IdlePowerUsageW
+ }
+ ElseIf ($Variables.MiningPowerUsage -gt 0) {
+ $Variables.Summary += "Power Cost / day: {1:N} {0} (Miner$(If ($Variables.BestMiners_Combo.Count -gt 1) { "s" }): {2:N} {0} [{3:0} W]; Base: {4:N} {0} [{5:0} W])" -f $Config.Currency, (($Variables.MiningPowerCost + $Variables.BasePowerCostBTC) * $Variables.Rates."BTC".($Config.Currency)), ($Variables.MiningPowerCost * $Variables.Rates."BTC".($Config.Currency)), $Variables.MiningPowerUsage, ($Variables.BasePowerCostBTC * $Variables.Rates."BTC".($Config.Currency)), $Config.IdlePowerUsageW
+ }
+ Else {
+ $Variables.Summary += "Power Cost / day: n/a (Miner: n/a; Base: {1:N} {0} [{2:0} W])" -f $Config.Currency, ($Variables.BasePowerCostBTC * $Variables.Rates.BTC.($Config.Currency)), $Config.IdlePowerUsageW
+ }
+ }
+ }
+ If ($Variables.Summary -ne "") { $Variables.Summary += "
" }
+
+ # Add currency conversion rates
+ @(@(If ($Config.UsemBTC -eq $true) { "mBTC" } Else { "BTC" }) + @($Config.ExtraCurrencies)) | Select-Object -Unique | Where-Object { $Variables.Rates.$_.($Config.Currency) } | ForEach-Object {
+ $Variables.Summary += "1 $_ = {0:N} $($Config.Currency) " -f $Variables.Rates.$_.($Config.Currency)
+ }
+ }
+ Else {
+ $Variables.Summary = "Error: Could not get BTC exchange rate from min-api.cryptocompare.com"
+ }
+
+ # Stop running miners
+ ForEach ($Miner in @(@($Miners | Where-Object Info) + @($CompareMiners | Where-Object { $_.Info -and $_.SideIndicator -EQ "<=" } <# miner object is gone #>))) {
+ If ($Miner.Status -eq [MinerStatus]::Failed) {
+ If ($Miner.ProcessID) { # Stop miner (may be set as failed in miner.refresh() because of 0 hash rate)
+ $Miner.StatusMessage = "Miner '$($Miner.Name) $($Miner.Info)' exited unexpectedly."
+ $Miner.SetStatus([MinerStatus]::Failed)
+ }
+ $Miner.Info = ""
+ $Miner.WorkersRunning = @()
+ }
+ ElseIf ($Miner.GetStatus() -ne [MinerStatus]::Running) {
+ $Miner.StatusMessage = "Miner '$($Miner.Name) $($Miner.Info)' exited unexpectedly."
+ $Miner.SetStatus([MinerStatus]::Failed)
+ $Miner.Info = ""
+ $Miner.WorkersRunning = @()
+ }
+ ElseIf ($Miner.Best -eq $false -or $Miner.Restart -eq $true -or $Miner.SideIndicator -eq "<=") {
+ ForEach ($Worker in $Miner.WorkersRunning) {
+ If ($WatchdogTimers = @($Variables.WatchdogTimers | Where-Object MinerName -EQ $Miner.Name | Where-Object PoolName -EQ $Worker.Pool.Name | Where-Object PoolRegion -EQ $Worker.Pool.Region | Where-Object Algorithm -EQ $Worker.Pool.Algorithm | Where-Object DeviceName -EQ $Miner.DeviceName)) {
+ # Remove Watchdog timers
+ $Variables.WatchdogTimers = @($Variables.WatchdogTimers | Where-Object { $_ -notin $WatchdogTimers })
+ }
+ Remove-Variable WatchdogTimers
+ }
+ $Miner.SetStatus([MinerStatus]::Idle)
+ $Miner.Info = ""
+ $Miner.WorkersRunning = @()
+ }
+ }
+
+ # Kill stray miners
+ $Loops = 0
+ While ($StrayMiners = @((Get-CimInstance CIM_Process | Where-Object ExecutablePath | Where-Object { @($Variables.Miners.Path | Sort-Object -Unique) -contains $_.ExecutablePath } | Where-Object { $Variables.Miners.ProcessID -notcontains $_.ProcessID }).ProcessID)) {
+ $StrayMiners | ForEach-Object { Stop-Process -Id $_ -Force -ErrorAction SilentlyContinue }
+ Start-Sleep -MilliSeconds 500
+ $Loops ++
+ If ($Loops -gt 100) {
+ Start-Sleep -Seconds 10
+ Write-Message -Level Error "Error stopping stray miner$(If($StrayMiners.Count -gt 1) { "s" }): $(($StrayMiners | ForEach-Object { (Get-Process -Id $_ -FileVersionInfo).FileName.Replace("$($Variables.MainPath)\", '') }) -join '; ')."
+ }
+ }
+ Remove-Variable Loops, StrayMiners
+
+ # Faster shutdown
+ If ($Variables.NewMiningStatus -ne "Running" -or $Variables.IdleRunspace.NewMiningStatus -eq "Idle") { Break }
+
+ If (-not ($Variables.Miners | Where-Object Available -EQ $true)) {
+ Write-Message -Level Warn "No miners available - retrying in 10 seconds..."
+ Start-Sleep -Seconds 10
+ Continue
+ }
+
+ Remove-Variable CompareMiners, Miner, Miners, WatchdogTimer, Worker -ErrorAction Ignore
+
+ # Optional delay to avoid blue screens
+ Start-Sleep -Seconds $Config.Delay -ErrorAction Ignore
+
+ ForEach ($Miner in ($Variables.Miners | Where-Object Best -EQ $true)) {
+
+ If ($Miner.Benchmark -eq $true -or $Miner.MeasurePowerUsage -eq $true) {
+ $DataCollectInterval = 1
+ $Miner.Data = @()
+ $Miner.Speed_Live = @()
+ $Miner.Earning = [Double]::NaN
+ $Miner.Earning_Bias = [Double]::NaN
+ If ($Miner.MeasurePowerUsage -eq $true) {
+ $Miner.Profit = [Double]::NaN
+ $Miner.Profit_Bias = [Double]::NaN
+ $Miner.PowerUsage = [Double]::NaN
+ $Miner.PowerUsage_Live = [Double]::NaN
+ }
+ }
+ Else {
+ $DataCollectInterval = 5
+ }
+
+ If ($Miner.GetStatus() -ne [MinerStatus]::Running) {
+ # Launch prerun if exists
+ If ($Miner.Type -eq "AMD" -and (Test-Path -Path ".\Utils\Prerun\AMDPrerun.bat" -PathType Leaf)) {
+ Start-Process ".\Utils\Prerun\AMDPrerun.bat" -WorkingDirectory ".\Utils\Prerun" -WindowStyle hidden
+ }
+ ElseIf ($Miner.Type -eq "NVIDIA" -and (Test-Path -Path ".\Utils\Prerun\NVIDIAPrerun.bat" -PathType Leaf)) {
+ Start-Process ".\Utils\Prerun\NVIDIAPrerun.bat" -WorkingDirectory ".\Utils\Prerun" -WindowStyle hidden
+ }
+ ElseIf ($Miner.Type -eq "CPU" -and (Test-Path -Path ".\Utils\Prerun\CPUPrerun.bat" -PathType Leaf)) {
+ Start-Process ".\Utils\Prerun\CPUPrerun.bat" -WorkingDirectory ".\Utils\Prerun" -WindowStyle hidden
+ }
+ If ($Miner.Type -ne "CPU") {
+ $MinerAlgorithmPrerunName = ".\Utils\Prerun\$($Miner.Name)$(If ($Miner.Algorithm.Count -eq 1) { "_$($Miner.Algorithm[0])" }).bat"
+ $AlgorithmPrerunName = ".\Utils\Prerun\$($Miner.Algorithm).bat"
+ $DefaultPrerunName = ".\Utils\Prerun\default.bat"
+ If (Test-Path $MinerAlgorithmPrerunName -PathType Leaf) {
+ Write-Message -Level Info "Launching Prerun: $MinerAlgorithmPrerunName"
+ Start-Process $MinerAlgorithmPrerunName -WorkingDirectory ".\Utils\Prerun" -WindowStyle hidden
+ Start-Sleep -Seconds 2
+ }
+ ElseIf (Test-Path $AlgorithmPrerunName -PathType Leaf) {
+ Write-Message -Level Info "Launching Prerun: $AlgorithmPrerunName"
+ Start-Process $AlgorithmPrerunName -WorkingDirectory ".\Utils\Prerun" -WindowStyle hidden
+ Start-Sleep -Seconds 2
+ }
+ ElseIf (Test-Path $DefaultPrerunName -PathType Leaf) {
+ Write-Message -Level Info "Launching Prerun: $DefaultPrerunName"
+ Start-Process $DefaultPrerunName -WorkingDirectory ".\Utils\Prerun" -WindowStyle hidden
+ Start-Sleep -Seconds 2
+ }
+ }
+ # Add extra time when CPU mining and miner requires DAG creation
+ If ($Miner.Workers.Pool.DAGsize -and ($Variables.Miners | Where-Object Best -EQ $true).Devices.Type -contains "CPU") { $Miner.WarmupTimes[0] += 15 <# seconds #>}
+
+ $Miner.DataCollectInterval = $DataCollectInterval
+ $Miner.SetStatus([MinerStatus]::Running)
+
+ # Add watchdog timer
+ If ($Config.Watchdog) {
+ ForEach ($Worker in $Miner.Workers) {
+ $Variables.WatchdogTimers += [PSCustomObject]@{
+ MinerName = $Miner.Name
+ MinerBaseName = $Miner.BaseName
+ MinerVersion = $Miner.Version
+ PoolName = $Worker.Pool.Name
+ PoolRegion = $Worker.Pool.Region
+ Algorithm = $Worker.Pool.Algorithm
+ DeviceName = [String[]]$Miner.DeviceName
+ Kicked = (Get-Date).ToUniversalTime()
+ }
+ }
+ }
+ }
+ ElseIf ($Miner.DataCollectInterval -ne $DataCollectInterval) {
+ $Miner.DataCollectInterval = $DataCollectInterval
+ $Miner.RestartDataReader()
+ }
+
+ If ($Miner.Activated -le 0) { $Miner.Activated = 1 } # Stat just got removed (Miner.Activated < 1, set by API)
+
+ $Message = ""
+ If ($Miner.Benchmark -eq $true) { $Message = "Benchmark " }
+ If ($Miner.Benchmark -eq $true -and $Miner.MeasurePowerUsage -eq $true) { $Message = "$($Message)and " }
+ If ($Miner.MeasurePowerUsage -eq $true) { $Message = "$($Message)Power usage measurement " }
+ If ($Message) { Write-Message -Level Verbose "$($Message)for miner '$($Miner.Name) $($Miner.Info)' in progress [Attempt $($Miner.Activated) of $($Variables.WatchdogCount + 1); min. $($Miner.MinDataSamples) Samples]..." }
+ }
+ Remove-Variable AlgorithmPrerunName, DefaultPrerunName, Message, Miner, MinerAlgorithmPrerunName, Worker -ErrorAction Ignore
+
+ $Variables.Miners | Where-Object Available -EQ $true | Group-Object { $_.DeviceName -join ';' } | ForEach-Object {
+ $MinersDeviceGroup = $_.Group
+ $MinersDeviceGroupNeedingBenchmark = $MinersDeviceGroup | Where-Object Benchmark -EQ $true
+ $MinersDeviceGroupNeedingPowerUsageMeasurement = $MinersDeviceGroup | Where-Object MeasurePowerUsage -EQ $true
+
+ # Display benchmarking progress
+ If ($MinersDeviceGroupNeedingBenchmark) {
+ Write-Message -Level Verbose "Benchmarking for device$(If (($MinersDeviceGroupNeedingBenchmark.DeviceName | Select-Object -Unique).Count -gt 1) { " group" }) '$(($MinersDeviceGroupNeedingBenchmark.DeviceName | Sort-Object -Unique) -join '; ')' in progress: $($MinersDeviceGroupNeedingBenchmark.Count) miner$(If ($MinersDeviceGroupNeedingBenchmark.Count -gt 1){ 's' }) left to complete benchmark."
+ }
+ # Display power usage measurement progress
+ If ($MinersDeviceGroupNeedingPowerUsageMeasurement) {
+ Write-Message -Level Verbose "Power usage measurement for device$(If (($MinersDeviceGroupNeedingPowerUsageMeasurement.DeviceName | Select-Object -Unique).Count -gt 1) { " group" }) '$(($MinersDeviceGroupNeedingPowerUsageMeasurement.DeviceName | Sort-Object -Unique) -join '; ')' in progress: $($MinersDeviceGroupNeedingPowerUsageMeasurement.Count) miner$(If ($MinersDeviceGroupNeedingPowerUsageMeasurement.Count -gt 1) { 's' }) left to complete measuring."
+ }
+ }
+ Remove-Variable MinersDeviceGroup, MinersDeviceGroupNeedingBenchmark, MinersDeviceGroupNeedingPowerUsageMeasurement -ErrorAction Ignore
+
+ Get-Job -State "Completed" | Remove-Job -Force -ErrorAction Ignore
+ Get-Job -State "Stopped" | Remove-Job -Force -ErrorAction Ignore
+
+ $Variables.StatusText = "Waiting $($Variables.TimeToSleep) seconds... | Next refresh: $((Get-Date).AddSeconds($Variables.TimeToSleep).ToString('g'))"
+ $Variables.RefreshNeeded = $true
+ $ExitLoopMessage = ""
+
+ # Faster shutdown
+ If ($Variables.NewMiningStatus -ne "Running" -or $Variables.IdleRunspace.NewMiningStatus -eq "Idle") { Break }
+
+ If ((Get-Date).ToUniversalTime() -le $Variables.EndLoopTime) {
+ Write-Message -Level Info "Collecting miner data while waiting for next cycle..."
+
+ $RunningMiners = @($Variables.Miners | Where-Object WorkersRunning | Sort-Object -Descending Benchmark, MeasurePowerUsage) # All miners with WorkersRunning should be running
+
+ # End loop when
+ # - a miner crashed (and no other miners are benchmarking or measuring power usage)
+ # - all benchmarking miners have collected enough samples
+ # - WarmupTimes[0] is reached (no readout from miner)
+ Do {
+ ForEach ($Miner in $RunningMiners) {
+ # Set window title
+ $WindowTitle = "$(($Miner.Devices.Name | Sort-Object) -join "; "): $($Miner.Name) $($Miner.Info)"
+ If ($Miner.Benchmark -eq $true -or $Miner.MeasurePowerUsage -eq $true) {
+ $WindowTitle += " ("
+ If ($Miner.Benchmark -eq $true) { $WindowTitle += "Benchmarking" }
+ If ($Miner.Benchmark -eq $true -and $Miner.MeasurePowerUsage -eq $true) { $WindowTitle += " and " }
+ If ($Miner.MeasurePowerUsage -eq $true) { $WindowTitle += "Measuring Power Usage" }
+ $WindowTitle += ")"
+ }
+ [Void][Win32]::SetWindowText((Get-Process -Id $Miner.ProcessId -ErrorAction Ignore).mainWindowHandle, $WindowTitle)
+ Remove-Variable WindowTitle
+ If ($Miner.GetStatus() -ne [MinerStatus]::Running) {
+ # Miner crashed
+ $Miner.StatusMessage = "Miner '$($Miner.Name) $($Miner.Info)' exited unexpectedly."
+ $Miner.SetStatus([MinerStatus]::Failed)
+ }
+ ElseIf ($Miner.DataReaderJob.State -ne [MinerStatus]::Running) {
+ # Miner data reader process failed
+ $Miner.StatusMessage = "Miner data reader '$($Miner.Name) $($Miner.Info)' exited unexpectedly."
+ $Miner.SetStatus([MinerStatus]::Failed)
+ }
+ ElseIf ($Miner.DataReaderJob.HasMoreData) {
+ # Set miner priority, some miners reset priority on their own
+ If ($Process = Get-Process | Where-Object Id -EQ $Miner.ProcessId) {
+ If ($Process.PriorityClass -ne $Global:PriorityNames.($Miner.ProcessPriority)) { $Process.PriorityClass = $Global:PriorityNames.($Miner.ProcessPriority) }
+ }
+ Remove-Variable Process -ErrorAction Ignore
+
+ $Miner.Data += $Samples = @($Miner.DataReaderJob | Receive-Job | Select-Object)
+ $Sample = $Samples | Select-Object -Last 1
+
+ If ((Get-Date) -gt $Miner.Process.PSBeginTime.AddSeconds($Miner.WarmupTimes[0])) {
+ # We must have data samples by now
+ If (($Miner.Data | Select-Object -Last 1).Date -lt $Miner.Process.PSBeginTime.ToUniversalTime()) {
+ # Miner has not provided first sample on time
+ $Miner.StatusMessage = "Miner '$($Miner.Name) $($Miner.Info)' has not provided first data sample in $($Miner.WarmupTimes[0]) seconds."
+ $Miner.SetStatus([MinerStatus]::Failed)
+ Break
+ }
+ ElseIf (($Miner.Data | Select-Object -Last 1).Date.AddSeconds(3.5 * $Miner.DataCollectInterval) -lt (Get-Date).ToUniversalTime()) {
+ # Miner stuck - no sample 10 seconds
+ $Miner.StatusMessage = "Miner '$($Miner.Name) $($Miner.Info)' has not updated data for more than $([Int](3.5 * $Miner.DataCollectInterval)) seconds."
+ $Miner.SetStatus([MinerStatus]::Failed)
+ Break
+ }
+ }
+
+ If ($Sample.Hashrate) {
+ $Miner.Speed_Live = $Sample.Hashrate.PSObject.Properties.Value
+ If (-not ($Miner.Data | Where-Object Date -GT $Miner.Process.PSBeginTime.ToUniversalTime().AddSeconds($Miner.WarmupTimes[1]))) {
+ Write-Message -Level Verbose "$($Miner.Name) data sample discarded [$(($Miner.WorkersRunning.Pool.Algorithm | ForEach-Object { "$($_): $(($Sample.Hashrate.$_ | ConvertTo-Hash) -replace ' ')$(If ($Config.BadShareRatioThreshold) { " / Shares Total: $($Sample.Shares.$_[2]), Rejected: $($Sample.Shares.$_[1])" })" }) -join ' & ')$(If ($Sample.PowerUsage) { " / Power usage: $($Sample.PowerUsage.ToString("N2"))W" })] (miner is warming up)."
+ $Miner.Data = @($Miner.Data | Where-Object Date -LT $Miner.Process.PSBeginTime.ToUniversalTime())
+ }
+ Else {
+ If ($Miner.StatusMessage -notlike "Mining *") {
+ $Miner.StatusMessage = "$(If ($Miner.Benchmark -eq $true -or $Miner.MeasurePowerUsage -eq $true) { "$($(If ($Miner.Benchmark -eq $true) { "Benchmarking" }), $(If ($Miner.Benchmark -eq $true -and $Miner.MeasurePowerUsage -eq $true) { "and" }), $(If ($Miner.MeasurePowerUsage -eq $true) { "Power usage measuring" }) -join ' ')" } Else { "Mining" }) {$(($Miner.Workers.Pool | ForEach-Object { (($_.Algorithm | Select-Object), ($_.Name | Select-Object)) -join '@' }) -join ' & ')}"
+ $Miner.Devices | ForEach-Object { $_.Status = $Miner.StatusMessage }
+ }
+ Write-Message -Level Verbose "$($Miner.Name) data sample retrieved [$(($Miner.WorkersRunning.Pool.Algorithm | ForEach-Object { "$($_): $(($Sample.Hashrate.$_ | ConvertTo-Hash) -replace ' ')$(If ($Config.BadShareRatioThreshold) { " / Shares Total: $($Sample.Shares.$_[2]), Rejected: $($Sample.Shares.$_[1])" })" }) -join ' & ')$(If ($Sample.PowerUsage) { " / Power usage: $($Sample.PowerUsage.ToString("N2"))W" })] ($($Miner.Data.Count) sample$(If ($Miner.Data.Count -ne 1) { "s" }))."
+ }
+ }
+ }
+ }
+
+ $FailedMiners = @($RunningMiners | Where-Object { $_.Status -ne [MinerStatus]::Running })
+ $RunningMiners = @($RunningMiners | Where-Object { $_.Status -eq [MinerStatus]::Running })
+ $BenchmarkingOrMeasuringMiners = @($RunningMiners | Where-Object { $_.Benchmark -eq $true -or $_.MeasurePowerUsage -eq $true })
+
+ If ($FailedMiners -and -not $BenchmarkingOrMeasuringMiners) {
+ # A miner crashed and we're not benchmarking, end the loop now
+ $ExitLoopMessage = " prematurely (Miner failed)"
+ Break
+ }
+ ElseIf ($BenchmarkingOrMeasuringMiners -and (-not ($BenchmarkingOrMeasuringMiners | Where-Object { $_.Data.Count -lt (($Config.MinDataSamples, ($BenchmarkingOrMeasuringMiners.MinDataSamples | Measure-Object -Minimum).Minimum) | Measure-Object -Maximum).Maximum }))) {
+ # Enough samples collected for this loop, exit loop immediately
+ $ExitLoopMessage = " prematurely (All$(If ($BenchmarkingOrMeasuringMiners | Where-Object Benchmark -EQ $true) { " benchmarking" })$(If ($BenchmarkingOrMeasuringMiners | Where-Object { $_.Benchmark -eq $true -and $_.MeasurePowerUsage -eq $true }) { " and" })$(If ($BenchmarkingOrMeasuringMiners | Where-Object MeasurePowerUsage -EQ $true) { " power usage measuring" }) miners have collected enough samples for this cycle)"
+ Break
+ }
+ ElseIf (-not $RunningMiners) {
+ # No more running miners, end the loop now
+ $ExitLoopMessage = " prematurely (No more running miners)"
+ Break
+ }
+ ElseIf ($Variables.NewMiningStatus -ne "Running" -or $Variables.IdleRunspace.NewMiningStatus -eq "Idle") {
+ # Faster shutdown
+ Break
+ }
+
+ Start-Sleep -Milliseconds 100
+
+ } While ((Get-Date).ToUniversalTime() -le $Variables.EndLoopTime -or $BenchmarkingOrMeasuringMiners)
+
+ Remove-Variable BenchmarkingOrMeasuringMiners, FailedMiners, Interval, Message, Miner, NextLoop, RunningMiners, Sample, Samples -ErrorAction SilentlyContinue
+
+ Break
+ }
+
+ Break # Exit non-idle loop
+ }
+
+ If ($Variables.NewMiningStatus -eq "Running") {
+ If ($Variables.IdleRunspace.NewMiningStatus -eq "Idle") { $ExitLoopMessage = " (System activity detected)" }
+ Write-Message -Level Info "Ending cycle$($ExitLoopMessage)."
+ }
+ Remove-Variable ExitLoopMessage -ErrorAction Ignore
+
+ If ($Variables.IdleRunspace.NewMiningStatus -eq "Idle") {
+ Stop-MiningProcess
+ $Variables.Summary = "Mining is suspended until system is idle again for $($Config.IdleSec) second$(If ($Config.IdleSec -ne 1) { "s" })..."
+ Write-Message -Level Verbose $Variables.Summary
+ Do {
+ Start-Sleep -Seconds 1
+ } While ($Variables.NewMiningStatus -eq "Running" -and $Config.MineWhenIdle -and $Variables.IdleRunspace.NewMiningStatus -eq "Idle")
+ }
+
+ $Error.Clear()
+}
diff --git a/Includes/DataReader.ps1 b/Includes/DataReader.ps1
new file mode 100644
index 0000000000..68067b8325
--- /dev/null
+++ b/Includes/DataReader.ps1
@@ -0,0 +1,148 @@
+Add-Type -TypeDefinition @'
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Management.Automation;
+using System.Management.Automation.Runspaces;
+namespace InProcess
+{
+ public class InMemoryJob : System.Management.Automation.Job
+ {
+ public InMemoryJob(PowerShell PowerShell, string name)
+ {
+ _PowerShell = PowerShell;
+ SetUpStreams(name);
+ }
+ private void SetUpStreams(string name)
+ {
+ _PowerShell.Streams.Verbose = this.Verbose;
+ _PowerShell.Streams.Error = this.Error;
+ _PowerShell.Streams.Debug = this.Debug;
+ _PowerShell.Streams.Warning = this.Warning;
+ _PowerShell.Streams.Information = this.Information;
+ _PowerShell.Runspace.AvailabilityChanged += new EventHandler
(Runspace_AvailabilityChanged);
+ int id = System.Threading.Interlocked.Add(ref InMemoryJobNumber, 1);
+ if (!string.IsNullOrEmpty(name))
+ {
+ this.Name = name;
+ }
+ else
+ {
+ this.Name = "InProcessJob" + id;
+ }
+ }
+ void Runspace_AvailabilityChanged(object sender, RunspaceAvailabilityEventArgs e)
+ {
+ if (e.RunspaceAvailability == RunspaceAvailability.Available)
+ {
+ this.SetJobState(JobState.Completed);
+ }
+ }
+ PowerShell _PowerShell;
+ static int InMemoryJobNumber = 0;
+ public override bool HasMoreData
+ {
+ get {
+ return (Output.Count > 0);
+ }
+ }
+ public override string Location
+ {
+ get { return "In Process"; }
+ }
+ public override string StatusMessage
+ {
+ get { return "A new status message"; }
+ }
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (!isDisposed)
+ {
+ isDisposed = true;
+ try
+ {
+ if (!IsFinishedState(JobStateInfo.State))
+ {
+ StopJob();
+ }
+ foreach (Job job in ChildJobs)
+ {
+ job.Dispose();
+ }
+ }
+ finally
+ {
+ base.Dispose(disposing);
+ }
+ }
+ }
+ }
+ private bool isDisposed = false;
+ internal bool IsFinishedState(JobState state)
+ {
+ return (state == JobState.Completed || state == JobState.Failed || state == JobState.Stopped);
+ }
+ public override void StopJob()
+ {
+ _PowerShell.Stop();
+ _PowerShell.EndInvoke(_asyncResult);
+ SetJobState(JobState.Stopped);
+ }
+ public void Start()
+ {
+ _asyncResult = _PowerShell.BeginInvoke(null, Output);
+ SetJobState(JobState.Running);
+ }
+ IAsyncResult _asyncResult;
+ public void WaitJob()
+ {
+ _asyncResult.AsyncWaitHandle.WaitOne();
+ }
+ public void WaitJob(TimeSpan timeout)
+ {
+ _asyncResult.AsyncWaitHandle.WaitOne(timeout);
+ }
+ }
+}
+'@
+
+function Start-JobInProcess {
+ [CmdletBinding()]
+ Param
+ (
+ [ScriptBlock] $ScriptBlock,
+ $ArgumentList,
+ [String] $Name
+ )
+
+ Function Get-JobRepository {
+ [CmdletBinding()]
+ Param()
+ $PScmdlet.JobRepository
+ }
+
+ Function Add-Job {
+ [CmdletBinding()]
+ Param
+ (
+ $Job
+ )
+ $PScmdlet.JobRepository.Add($Job)
+ }
+
+ $PowerShell = [PowerShell]::Create().AddScript($ScriptBlock)
+
+ if ($ArgumentList) {
+ $ArgumentList | ForEach-Object {
+ $PowerShell.AddArgument($_)
+ }
+ }
+
+ $MemoryJob = New-Object InProcess.InMemoryJob $PowerShell, $Name
+
+ $MemoryJob.Start()
+ Add-Job $MemoryJob
+ $MemoryJob
+}
diff --git a/Includes/Downloader.ps1 b/Includes/Downloader.ps1
new file mode 100644
index 0000000000..2218c5517b
--- /dev/null
+++ b/Includes/Downloader.ps1
@@ -0,0 +1,77 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: Downloader.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+using module .\Includes\Include.psm1
+
+$Config = $args.Config
+$DownloadList = $args.DownloadList
+$Variables = $args.Variables
+
+$ProgressPreference = "SilentlyContinue"
+
+$DownloadList | Select-Object | ForEach-Object {
+ $URI = $_.URI
+ $Path = $_.Path
+ $Searchable = $_.Searchable
+
+ If (-not (Test-Path $Path -PathType Leaf)) {
+ Try {
+ Write-Message "Downloader: Initiated download of '$URI'."
+
+ If ($URI -and (Split-Path $URI -Leaf) -eq (Split-Path $Path -Leaf)) {
+ New-Item (Split-Path $Path) -ItemType "Directory" | Out-Null
+ Invoke-WebRequest $URI -OutFile $Path -UseBasicParsing -ErrorAction Stop
+ }
+ Else {
+ Expand-WebRequest $URI $Path -ErrorAction Stop
+ }
+ Write-Message "Downloader: Installed downloaded miner binary '$Path'."
+ }
+ Catch {
+ $Path_Old = $null
+
+ If ($URI) { Write-Message -Level Warn "Downloader: Cannot download '$(Split-Path $Path -Leaf)' distributed at '$URI'." }
+ Else { Write-Message -Level Warn "Downloader: Cannot download '$(Split-Path $Path -Leaf)'." }
+
+ If ($Searchable) {
+ Write-Message "Downloader: Searching for $(Split-Path $Path -Leaf) on local computer..."
+
+ $Path_Old = Get-PSDrive -PSProvider FileSystem | ForEach-Object { Get-ChildItem -Path $_.Root -Include (Split-Path $Path -Leaf) -Recurse -ErrorAction Ignore } | Sort-Object LastWriteTimeUtc -Descending | Select-Object -First 1
+ $Path_New = $Path
+ }
+
+ If ($Path_Old) {
+ If (Test-Path (Split-Path $Path_New) -PathType Container) { (Split-Path $Path_New) | Remove-Item -Recurse -Force }
+ (Split-Path $Path_Old) | Copy-Item -Destination (Split-Path $Path_New) -Recurse -Force
+ Write-Message -Level Verbose "Downloader: Copied '$Path' from local repository '$PathOld'."
+ }
+ Else {
+ If ($URI) { Write-Message -Level Warn "Downloader: Cannot find '$Path' distributed at '$URI'." }
+ Else { Write-Message -Level Warn "Downloader: Cannot find '$Path'." }
+ }
+ }
+ }
+}
+
+Write-Message "Downloader: All tasks complete."
diff --git a/Includes/Include.psm1 b/Includes/Include.psm1
new file mode 100644
index 0000000000..9c3e586c84
--- /dev/null
+++ b/Includes/Include.psm1
@@ -0,0 +1,3096 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: include.ps1
+Version: 4.0.0.28
+Version date: 30 April 2022
+#>
+
+# Window handling
+Add-Type -TypeDefinition @"
+using System;
+using System.Runtime.InteropServices;
+
+public static class Win32 {
+ [DllImport("user32.dll")]
+ public static extern int SetWindowText(IntPtr hWnd, string strTitle);
+
+ [DllImport("user32.dll")]
+ public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
+
+ [DllImport("user32.dll")]
+ public static extern int SetForegroundWindow(IntPtr hwnd);
+
+ [DllImport("user32.dll")]
+ public static extern IntPtr GetForegroundWindow();
+
+ [DllImport("user32.dll")]
+ public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
+}
+"@
+
+$Global:PriorityNames = [PSCustomObject]@{ -2 = "Idle"; -1 = "BelowNormal"; 0 = "Normal"; 1 = "AboveNormal"; 2 = "High"; 3 = "RealTime" }
+
+Class Device {
+ [String]$Name
+ [String]$Model
+ [String]$Vendor
+ [Int64]$Memory
+ [Double]$MemoryGB
+ [String]$Type
+ [PSCustomObject]$CIM
+ [PSCustomObject]$PNP
+ [PSCustomObject]$Reg
+ [PSCustomObject]$CpuFeatures
+
+ [String]$Status = "Idle"
+
+ [Int]$Bus
+ [Int]$Id
+ [Int]$Type_Id
+ [Int]$Vendor_Id
+ [Int]$Type_Vendor_Id
+
+ [Int]$Slot = 0
+ [Int]$Type_Slot
+ [Int]$Vendor_Slot
+ [Int]$Type_Vendor_Slot
+
+ [Int]$Index = 0
+ [Int]$Type_Index
+ [Int]$Type_Vendor_Index
+ [Int]$Vendor_Index
+ [Int]$Bus_Index
+ [Int]$Bus_Type_Index
+ [Int]$Bus_Vendor_Index
+
+ [Int]$PlatformId = 0
+ [Int]$PlatformId_Index
+ [Int]$Type_PlatformId_Index
+ [Int]$Bus_Platform_Index
+
+ [PSCustomObject]$OpenCL = [PSCustomObject]@{ }
+ [DeviceState]$State = [DeviceState]::Enabled
+ [Boolean]$ReadPowerUsage = $false
+ [Double]$ConfiguredPowerUsage = 0 # Workaround if device does not expose power usage
+}
+
+Enum DeviceState {
+ Enabled
+ Disabled
+ Unsupported
+}
+
+Class Pool {
+ # static [Credential[]]$Credentials = @()
+ # [Credential[]]$Credential = @()
+
+ [String]$Name
+ [String]$BaseName
+ [String]$Algorithm
+ [Nullable[Int]]$BlockHeight = $null
+ [Nullable[Int64]]$DAGsize = $null
+ [Nullable[Int]]$Epoch = $null
+ [String]$Currency = ""
+ [String]$CoinName = ""
+ [String]$Host
+ # [String[]]$Hosts # To be implemented for pool failover
+ [UInt16]$Port
+ [String]$User
+ [String]$Pass
+ [String]$Region
+ [Boolean]$SSL
+ [Double]$Fee
+ [Double]$EarningsAdjustmentFactor = 1
+ [DateTime]$Updated = (Get-Date).ToUniversalTime()
+ [Nullable[Int]]$Workers
+ [Boolean]$Available = $true
+ [String[]]$Reason = @("")
+ [Boolean]$Best = $false
+
+ # Stats
+ [Double]$Price
+ [Double]$Price_Bias
+ [Double]$StablePrice
+ [Double]$Accuracy
+}
+
+Class Worker {
+ [Pool]$Pool
+ [Double]$Fee
+ [Double]$Speed
+ [Double]$Earning
+ [Double]$Earning_Bias
+ [Double]$Earning_Accuracy
+ [Boolean]$Disabled
+ [TimeSpan]$TotalMiningDuration
+}
+
+Enum MinerStatus {
+ Running
+ Idle
+ Failed
+ Disabled
+}
+
+Class Miner {
+ static [Pool[]]$Pools = @()
+ [Worker[]]$Workers = @()
+ [Worker[]]$WorkersRunning = @()
+ [Device[]]$Devices = @()
+ [String]$Type
+
+ [String]$Name
+ [String]$BaseName
+ [String]$Version
+ [String]$Path
+ [String]$URI
+ [String]$Arguments
+ [String]$CommandLine
+ [UInt16]$Port
+ [String[]]$DeviceName = @() # derived from devices
+ [String[]]$Algorithm = @() # derived from workers
+ [String[]]$Pool = @() # derived from workers
+ [Double[]]$Speed_Live = @()
+
+ [Boolean]$Benchmark = $false # derived from stats
+
+ [Double]$Earning # derived from pool and stats
+ [Double]$Earning_Bias # derived from pool and stats
+ [Double]$Earning_Accuracy # derived from pool and stats
+ [Double]$Profit
+ [Double]$Profit_Bias
+
+ [Boolean]$ReadPowerUsage = $false
+ [Boolean]$MeasurePowerUsage = $false
+ [Boolean]$Prioritize = $false # derived from BalancesKeepAlive
+
+ [Double]$PowerUsage
+ [Double]$PowerUsage_Live
+ [Double]$PowerCost
+
+ [Boolean]$MostProfitable = $false
+ [Boolean]$Best = $false
+ [Boolean]$Available = $true
+ [Boolean]$Disabled = $false
+ [String[]]$Reason
+ [Boolean]$Restart = $false
+ [Boolean]$KeepRunning = $false # do not stop miner even if not best (MinInterval)
+
+ hidden [PSCustomObject[]]$Data = $null
+ hidden [System.Management.Automation.Job]$DataReaderJob = $null
+ hidden [System.Management.Automation.Job]$Process = $null
+ hidden [TimeSpan]$Active = [TimeSpan]::Zero
+
+ [Int32]$ProcessId = 0
+ [Int]$ProcessPriority = -1
+
+ [Int]$Activated = 0
+ [MinerStatus]$Status = [MinerStatus]::Idle
+ [String]$StatusMessage
+ [String]$Info
+ [DateTime]$StatStart
+ [DateTime]$StatEnd
+ [Int]$DataCollectInterval = 5 # Seconds
+ [String]$WindowStyle = "minimized"
+ [String[]]$EnvVars = @()
+ [Int]$MinDataSamples # for safe hashrate values
+ [PSCustomObject]$LastSample # last hash rate sample
+ [Int[]]$WarmupTimes # First value: time (in seconds) until first hash rate sample is valid (default 0, accept first sample), second value: time (in seconds) the miner is allowed to warm up, e.g. to compile the binaries or to get the API ready and providing first data samples before it get marked as failed (default 15)
+ [DateTime]$BeginTime
+ [DateTime]$EndTime
+ [TimeSpan]$TotalMiningDuration # derived from pool and stats
+
+ [String]$API
+ [String]$MinerUri
+ [String]$LogFile
+
+ [String[]]GetProcessNames() {
+ Return @(([IO.FileInfo]($this.Path | Split-Path -Leaf -ErrorAction Ignore)).BaseName)
+ }
+
+ [String]GetCommandLineParameters() {
+ Return (Get-CommandLineParameters $this.Arguments)
+ }
+
+ [String]GetCommandLine() {
+ Return "$($this.Path) $($this.GetCommandLineParameters())"
+ }
+
+ [Int32]GetProcessId() {
+ Return $this.ProcessId
+ }
+
+ hidden StartDataReader() {
+ $ScriptBlock = {
+ $ScriptBody = "using module .\Includes\Include.psm1"; $Script = [ScriptBlock]::Create($ScriptBody); . $Script
+ Try {
+ # Load miner API file
+ . ".\Includes\MinerAPIs\$($args[0]).ps1"
+ $Miner = ($args[1] | ConvertFrom-Json) -as $args[0]
+ While ($true) {
+ $NextLoop = (Get-Date).AddSeconds($Miner.DataCollectInterval)
+ $Miner.GetMinerData()
+ While ((Get-Date) -lt $NextLoop) { Start-Sleep -Milliseconds 50 }
+ }
+ }
+ Catch {
+ Return $Error[0]
+ }
+ }
+ # Start Miner data reader
+ $this | Add-Member -Force @{ DataReaderJob = Start-ThreadJob -Name "$($this.Name)_DataReader" -ThrottleLimit 99 -InitializationScript ([ScriptBlock]::Create("Set-Location('$(Get-Location)')")) -ScriptBlock $ScriptBlock -ArgumentList ($this.API), ($this | Select-Object -Property Algorithm, DataCollectInterval, Devices, Name, Path, Port, ReadPowerUsage, LogFile | ConvertTo-Json -WarningAction Ignore) }
+ }
+
+ hidden StopDataReader() {
+ # Stop Miner data reader
+ $this.DataReaderJob | Stop-Job -ErrorAction Ignore | Remove-Job -Force -ErrorAction Ignore
+ }
+
+ hidden RestartDataReader() {
+ # Read data if available before restarting
+ If ($this.DataReaderJob.HasMoreData) { $this.Data += @($this.DataReaderJob | Receive-Job | Select-Object) }
+ $this.StopDataReader()
+ $this.StartDataReader()
+ }
+
+ hidden StartMining() {
+ $this.Status = [MinerStatus]::Idle
+ $this.Info = "{$(($this.Workers.Pool | ForEach-Object { (($_.Algorithm | Select-Object), ($_.Name | Select-Object)) -join '@' }) -join ' & ')}"
+ $this.StatusMessage = "Starting $($this.Info)"
+ $this.Devices | ForEach-Object { $_.Status = $this.StatusMessage }
+ $this.Activated++
+
+ Write-Message -Level Info "Starting miner '$($this.Name) $($this.Info)'..."
+
+ If (Test-Json $this.Arguments -ErrorAction Ignore) { $this.CreateConfigFiles() }
+
+ If ($this.Process) {
+ If ($this.Process | Get-Job -ErrorAction SilentlyContinue) {
+ $this.Process | Remove-Job -Force -ErrorAction Ignore
+ }
+
+ If (-not ($this.Process | Get-Job -ErrorAction SilentlyContinue)) {
+ $this.Active += $this.Process.PSEndTime - $this.Process.PSBeginTime
+ $this.Process = $null
+ }
+ }
+
+ If (-not $this.Process) {
+ If ($this.Benchmark -EQ $true -or $this.MeasurePowerUsage -EQ $true) { $this.Data = @() } # When benchmarking clear data on each miner start
+ $this.Process = Invoke-CreateProcess -BinaryPath $this.Path -ArgumentList $this.GetCommandLineParameters() -WorkingDirectory (Split-Path $this.Path) -MinerWindowStyle $this.WindowStyle -Priority $this.ProcessPriority -EnvBlock $this.EnvVars -JobName $this.Name -LogFile $this.LogFile
+ $this.Status = [MinerStatus]::Running
+ Write-Message -Level Verbose $this.CommandLine
+
+ # Log switching information to .\Logs\SwitchingLog.csv
+ [PSCustomObject]@{
+ DateTime = (Get-Date -Format o)
+ Action = "Launched"
+ Name = $this.Name
+ Device = ($this.Devices.Name | Sort-Object) -join "; "
+ Type = $this.Type
+ Account = ($this.Workers.Pool.User | ForEach-Object { $_ -split "\." | Select-Object -First 1 } | Select-Object -Unique) -join "; "
+ Pool = ($this.Workers.Pool.Name | Select-Object -Unique) -join "; "
+ Algorithm = $this.Workers.Pool.Algorithm -join "; "
+ Duration = ""
+ Earning = $this.Earning
+ Earning_Bias = $this.Earning_Bias
+ Profit = $this.Profit
+ Profit_Bias = $this.Profit_Bias
+ CommandLine = $this.CommandLine
+ Benchmark = $this.Benchmark
+ MeasurePowerUsage = $this.MeasurePowerUsage
+ Reason = ""
+ LastDataSample = $null
+ } | Export-Csv -Path ".\Logs\SwitchingLog.csv" -Append -NoTypeInformation -ErrorAction Ignore
+
+ If ($this.Process | Get-Job -ErrorAction SilentlyContinue) {
+ For ($WaitForPID = 0; $WaitForPID -le 20; $WaitForPID++) {
+ If ($this.ProcessId = [Int32]((Get-CimInstance CIM_Process | Where-Object { $_.ExecutablePath -eq $this.Path -and $_.CommandLine -eq "$($this.Path) $($this.GetCommandLineParameters())" }).ProcessId)) {
+ $this.StatusMessage = "Warming up $($this.Info)"
+ $this.Devices | ForEach-Object { $_.Status = $this.StatusMessage }
+ $this.StatStart = $this.BeginTime = (Get-Date).ToUniversalTime()
+ $this.StartDataReader()
+ $this.Speed_Live = @($this.Algorithm | ForEach-Object { [Double]::NaN })
+ $this.WorkersRunning = $this.Workers
+ Break
+ }
+ Start-Sleep -Milliseconds 100
+ }
+ }
+ Else {
+ $this.Status = [MinerStatus]::Failed
+ $this.StatusMessage = "Failed $($this.Info)"
+ $this.Devices | ForEach-Object { $_.Status = "Failed" }
+ }
+ }
+ }
+
+ [MinerStatus]GetStatus() {
+ If ($this.Process.State -eq [MinerStatus]::Running -and $this.ProcessId -and (Get-Process -Id $this.ProcessId -ErrorAction SilentlyContinue).ProcessName) { # Use ProcessName, some crashed miners are dead, but may still be found by their processId
+ Return [MinerStatus]::Running
+ }
+ ElseIf ($this.Status -eq [MinerStatus]::Running) {
+ Return [MinerStatus]::Failed
+ }
+ Else {
+ Return $this.Status
+ }
+ }
+
+ SetStatus([MinerStatus]$Status) {
+ Switch ($Status) {
+ "Running" {
+ If ($Status -eq $this.GetStatus()) { Return }
+ $this.StartMining()
+ }
+ "Idle" {
+ $this.StopMining()
+ }
+ Default {
+ $this.Status = [MinerStatus]::Failed
+ $this.StopMining()
+ }
+ }
+ }
+
+ hidden StopMining() {
+ If ($this.Status -eq [MinerStatus]::Running) {
+ $this.StatusMessage = "Stopping miner '$($this.Name) $($this.Info)'..."
+ Write-Message -Level Info $this.StatusMessage
+ }
+ Else {
+ Write-Message -Level ERROR $this.StatusMessage
+ }
+
+ # Stop Miner data reader
+ $this.StopDataReader()
+
+ $this.EndTime = (Get-Date).ToUniversalTime()
+
+ If ($this.ProcessId) {
+ If (Get-Process -Id $this.ProcessId -ErrorAction SilentlyContinue) {
+ Stop-Process -Id $this.ProcessId -Force -ErrorAction Ignore
+ }
+ $this.ProcessId = $null
+ }
+ If ($this.Process) {
+ $this.Process | Remove-Job -Force -ErrorAction Ignore
+ $this.Process = $null
+ }
+
+ $this.Status = If ($this.Status -eq [MinerStatus]::Running) { [MinerStatus]::Idle } Else { [MinerStatus]::Failed }
+ $this.Devices | ForEach-Object { $_.Status = $this.Status }
+ $this.Devices | Where-Object { $_.State -eq [DeviceState]::Disabled} | ForEach-Object { $_.Status = "Disabled (ExcludeDeviceName: '$($_.Name)')" }
+
+ # Log switching information to .\Logs\SwitchingLog
+ [PSCustomObject]@{
+ DateTime = (Get-Date -Format o)
+ Action = If ($this.Status -eq [MinerStatus]::Idle) { "Stopped" } Else { "Failed" }
+ Name = $this.Name
+ Device = ($this.Devices.Name | Sort-Object) -join "; "
+ Type = $this.Type
+ Account = ($this.WorkersRunning.Pool.User | ForEach-Object { $_ -split "\." | Select-Object -First 1 } | Select-Object -Unique) -join "; "
+ Pool = ($this.WorkersRunning.Pool.Name | Select-Object -Unique) -join "; "
+ Algorithm = $this.WorkersRunning.Pool.Algorithm -join "; "
+ Duration = "{0:hh\:mm\:ss}" -f ($this.EndTime - $this.BeginTime)
+ Earning = $this.Earning
+ Earning_Bias = $this.Earning_Bias
+ Profit = $this.Profit
+ Profit_Bias = $this.Profit_Bias
+ CommandLine = ""
+ Benchmark = $this.Benchmark
+ MeasurePowerUsage = $this.MeasurePowerUsage
+ Reason = If ($this.Status -eq [MinerStatus]::Failed) { $this.StatusMessage } Else { "" }
+ LastDataSample = $this.Data | Select-Object -Last 1 | ConvertTo-Json -Compress
+ } | Export-Csv -Path ".\Logs\SwitchingLog.csv" -Append -NoTypeInformation -ErrorAction Ignore
+
+ $this.WorkersRunning = @()
+ $this.StatusMessage = If ($this.Status -eq [MinerStatus]::Idle) { "Idle" } Else { "Failed $($this.Info)" }
+ }
+
+ [DateTime]GetActiveLast() {
+ If ($this.BeginTime -and $this.EndTime) {
+ Return $this.EndTime.ToUniversalTime()
+ }
+ ElseIf ($this.BeginTime) {
+ Return [DateTime]::Now.ToUniversalTime()
+ }
+ Else {
+ Return [DateTime]::MinValue.ToUniversalTime()
+ }
+ }
+
+ [TimeSpan]GetActiveTime() {
+ If ($this.BeginTime -and $this.EndTime) {
+ Return $this.Active + $this.EndTime - $this.BeginTime
+ }
+ ElseIf ($this.BeginTime) {
+ Return $this.Active + ((Get-Date) - $this.BeginTime)
+ }
+ Else {
+ Return $this.Active
+ }
+ }
+
+ [Double]GetPowerUsage() {
+ [Device]$Device = $null
+ $RegistryData = [PSCustomObject]@{ }
+ $RegistryEntry = [PSCustomObject]@{ }
+ $RegistryHive = "HKCU:\Software\HWiNFO64\VSB"
+ $TotalPowerUsage = [Double]0
+
+ # Read power usage
+ $RegistryData = Get-ItemProperty $RegistryHive -ErrorAction Ignore
+ ForEach ($Device in $this.Devices) {
+ If ($RegistryEntry = $RegistryData.PSObject.Properties | Where-Object { ($_.Value -split " ") -contains $Device.Name }) {
+ $TotalPowerUsage += [Double]($RegistryData.($RegistryEntry.Name -replace "Label", "Value") -split ' ' | Select-Object -First 1)
+ }
+ Else {
+ $TotalPowerUsage += [Double]$Device.ConfiguredPowerUsage # Use configured value
+ }
+ }
+ Return $TotalPowerUsage
+ }
+
+ [Double[]]CollectHashrate([String]$Algorithm = [String]$this.Algorithm, [Boolean]$Safe = $this.Benchmark) {
+ # Returns an array of two values (safe, unsafe)
+ $Hashrate_Average = [Double]0
+ $Hashrate_Variance = [Double]0
+
+ $Hashrate_Samples = @($this.Data | Where-Object { $_.Hashrate.$Algorithm }) # Do not use 0 valued samples
+
+ $Hashrate_Average = ($Hashrate_Samples.Hashrate.$Algorithm | Measure-Object -Average).Average
+ $Hashrate_Variance = $Hashrate_Samples.Hashrate.$Algorithm | Measure-Object -Average -Minimum -Maximum | ForEach-Object { If ($_.Average) { ($_.Maximum - $_.Minimum) / $_.Average } }
+
+ If ($Safe) {
+ If ($Hashrate_Samples.Count -lt 3 -or $Hashrate_Variance -gt 0.1) {
+ Return @(0, $Hashrate_Average)
+ }
+ Else {
+ Return @(($Hashrate_Average * (1 + $Hashrate_Variance / 2)), $Hashrate_Average)
+ }
+ }
+ Else {
+ Return @($Hashrate_Average, $Hashrate_Average)
+ }
+ }
+
+ [Double[]]CollectPowerUsage([Boolean]$Safe = $this.MeasurePowerUsage) {
+ # Returns an array of two values (safe, unsafe)
+ $PowerUsage_Average = [Double]0
+ $PowerUsage_Variance = [Double]0
+
+ $PowerUsage_Samples = @($this.Data | Where-Object PowerUsage) # Do not use 0 valued samples
+
+ $PowerUsage_Average = ($PowerUsage_Samples.PowerUsage | Measure-Object -Average).Average
+ $PowerUsage_Variance = $PowerUsage_Samples.PowerUsage | Measure-Object -Average -Minimum -Maximum | ForEach-Object { If ($_.Average) { ($_.Maximum - $_.Minimum) / $_.Average } }
+
+ If ($Safe) {
+ If ($PowerUsage_Samples.Count -lt 3 -or $PowerUsage_Variance -gt 0.1) {
+ Return @(0, $PowerUsage_Average)
+ }
+ Else {
+ Return @(($PowerUsage_Average * (1 + $PowerUsage_Variance / 2)), $PowerUsage_Average)
+ }
+ }
+ Else {
+ Return @($PowerUsage_Average, $PowerUsage_Average)
+ }
+ }
+
+ Refresh([Double]$PowerCostBTCperW, [Boolean]$CalculatePowerCost) {
+ $this.Reason = @()
+ $this.Available = $true
+ $this.Best = $false
+ $this.Disabled = $false
+
+ $this.Benchmark = $false
+
+ $this.Earning = 0
+ $this.Earning_Bias = 0
+ $this.Earning_Accuracy = 0
+
+ $this.MeasurePowerUsage = $false
+ $this.Prioritize = $false
+
+ $this.PowerUsage = [Double]::NaN
+ $this.PowerCost = [Double]::NaN
+ $this.Profit = [Double]::NaN
+ $this.Profit_Bias = [Double]::NaN
+
+ $this.Workers | ForEach-Object {
+ If ($Stat = Get-Stat "$($this.Name)_$($_.Pool.Algorithm)_Hashrate") {
+ $_.Speed = $Stat.Hour
+ $Factor = [Double]($_.Speed * (1 - $_.Fee) * (1 - $_.Pool.Fee))
+ $_.Earning = [Double]($_.Pool.Price * $Factor)
+ $_.Earning_Bias = [Double]($_.Pool.Price_Bias * $Factor)
+ $_.Earning_Accuracy = [Double]$_.Pool.Accuracy
+ $_.TotalMiningDuration = $Stat.Duration
+ $_.Disabled = $Stat.Disabled
+ $this.Earning += $_.Earning
+ $this.Earning_Bias += $_.Earning_Bias
+ }
+ Else {
+ $_.Disabled = $false
+ $_.Speed = [Double]::NaN
+ }
+ If ($_.Pool.Reason -contains "Prioritized by BalancesKeepAlive") { $this.Prioritize = $true }
+ }
+
+ If ($this.Workers | Where-Object Disabled) {
+ $this.Status = [MinerStatus]::Disabled
+ $this.Available = $false
+ $this.Disabled = $true
+ }
+ ElseIf ($this.Workers | Where-Object { [Double]::IsNaN($_.Speed) }) {
+ $this.Benchmark = $true
+ $this.Earning = [Double]::NaN
+ $this.Earning_Bias = [Double]::NaN
+ $this.Earning_Accuracy = [Double]::NaN
+ }
+ ElseIf ($this.Workers[0].Speed -EQ 0) { # Allow 0 hashrate on secondary algorithm
+ $this.Status = [MinerStatus]::Failed
+ $this.Available = $false
+ $this.Disabled = $false
+ $this.Earning = [Double]::NaN
+ $this.Earning_Bias = [Double]::NaN
+ $this.Earning_Accuracy = [Double]::NaN
+ }
+ Else { $this.Workers | ForEach-Object { $this.Earning_Accuracy += (($_.Earning_Accuracy * $_.Earning) / $this.Earning) } }
+ If ($this.Earning -eq 0) { $this.Earning_Accuracy = 0 }
+
+ $this.TotalMiningDuration = ($this.Workers.TotalMiningDuration | Measure-Object -Minimum).Minimum
+
+ If ($CalculatePowerCost) {
+ If ($Stat = Get-Stat "$($this.Name)$(If ($this.Workers.Count -eq 1) { "_$($this.Workers.Pool.Algorithm | Select-Object -First 1)" })_PowerUsage") {
+ $this.PowerUsage = $Stat.Week
+ $this.PowerCost = $this.PowerUsage * $PowerCostBTCperW
+ $this.Profit = $this.Earning - $this.PowerCost
+ $this.Profit_Bias = $this.Earning_Bias - $this.PowerCost
+ }
+ Else {
+ $this.MeasurePowerUsage = $true
+ }
+ }
+ }
+}
+Function Start-IdleDetection {
+
+ # Function tracks how long the system has been idle and controls the paused state
+ $IdleRunspace = [runspacefactory]::CreateRunspace()
+ $IdleRunspace.Open()
+ $IdleRunspace.SessionStateProxy.SetVariable('Config', $Config)
+ $IdleRunspace.SessionStateProxy.SetVariable('Variables', $Variables)
+ $IdleRunspace.SessionStateProxy.Path.SetLocation($Variables.MainPath)
+
+ $Variables.IdleRunspace = $IdleRunspace
+
+ $PowerShell = [PowerShell]::Create()
+ $PowerShell.Runspace = $IdleRunspace
+ $PowerShell.AddScript(
+ {
+ # Set the starting directory
+ Set-Location (Split-Path $MyInvocation.MyCommand.Path)
+
+ $ScriptBody = "using module .\Includes\Include.psm1"; $Script = [ScriptBlock]::Create($ScriptBody); . $Script
+
+ $Variables.IdleRunspace | Add-Member NewMiningStatus "Idle" -Force
+
+ # No native way to check how long the system has been idle in PowerShell. Have to use .NET code.
+ Add-Type -TypeDefinition @'
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace PInvoke.Win32 {
+
+ public static class UserInput {
+
+ [DllImport("user32.dll", SetLastError=false)]
+ private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct LASTINPUTINFO {
+ public uint cbSize;
+ public int dwTime;
+ }
+
+ public static DateTime LastInput {
+ get {
+ DateTime bootTime = DateTime.UtcNow.AddMilliseconds(-Environment.TickCount);
+ DateTime lastInput = bootTime.AddMilliseconds(LastInputTicks);
+ return lastInput;
+ }
+ }
+
+ public static TimeSpan IdleTime {
+ get {
+ return DateTime.UtcNow.Subtract(LastInput);
+ }
+ }
+
+ public static int LastInputTicks {
+ get {
+ LASTINPUTINFO lii = new LASTINPUTINFO();
+ lii.cbSize = (uint)Marshal.SizeOf(typeof(LASTINPUTINFO));
+ GetLastInputInfo(ref lii);
+ return lii.dwTime;
+ }
+ }
+ }
+}
+'@
+
+ $ProgressPreference = "SilentlyContinue"
+ $IdleSeconds = [Math]::Round(([PInvoke.Win32.UserInput]::IdleTime).TotalSeconds)
+
+ Write-Message -Level Verbose "Started idle detection.$(If ($IdleSeconds -le $Config.IdleSec) { " $($Variables.Branding.ProductLabel) will start mining when the system is idle for more than $($Config.IdleSec) second$(If ($Config.IdleSec -ne 1) { "s" })..." })"
+
+ While ($true) {
+ $IdleSeconds = [Math]::Round(([PInvoke.Win32.UserInput]::IdleTime).TotalSeconds)
+
+ # Activity detected, pause mining
+ If ($IdleSeconds -lt $Config.IdleSec -and $Variables.IdleRunspace.NewMiningStatus -ne "Idle") {
+ $Variables.IdleRunspace | Add-Member NewMiningStatus "Idle" -Force
+
+ $LabelMiningStatus.Text = "Idle | $($Variables.Branding.ProductLabel) $($Variables.Branding.Version)"
+ $LabelMiningStatus.ForeColor = [System.Drawing.Color]::Green
+ }
+
+ # System has been idle long enough, start mining
+ If ($IdleSeconds -ge $Config.IdleSec -and $Variables.IdleRunspace.NewMiningStatus -ne "Mining") {
+ $Variables.IdleRunspace | Add-Member NewMiningStatus "Mining" -Force
+
+ $LabelMiningStatus.Text = "Running | $($Variables.Branding.ProductLabel) $($Variables.Branding.Version)"
+ $LabelMiningStatus.ForeColor = [System.Drawing.Color]::Green
+ }
+ Start-Sleep -Seconds 1
+ }
+ }
+ ) | Out-Null
+ $PowerShell.BeginInvoke()
+
+ $Variables.IdleRunspace | Add-Member -Force @{ PowerShell = $PowerShell }
+}
+
+Function Stop-IdleDetection {
+
+ If ($Variables.IdleRunspace) {
+ $Variables.IdleRunspace.Close()
+ If ($Variables.IdleRunspace.PowerShell) { $Variables.IdleRunspace.PowerShell.Dispose() }
+ $Variables.Remove("IdleRunspace")
+ Write-Message -Level Verbose "Stopped idle detection."
+ }
+}
+
+Function Start-Mining {
+
+ If (-not $Variables.CoreRunspace) {
+ $Variables.Summary = "Starting mining processes..."
+ Write-Message -Level Info $Variables.Summary
+
+ $Variables.Timer = $null
+ $Variables.LastDonated = (Get-Date).AddDays(-1).AddHours(1)
+ $Variables.Pools = $null
+ $Variables.Miners = $null
+
+ $CoreRunspace = [RunspaceFactory]::CreateRunspace()
+ $CoreRunspace.Open()
+ $CoreRunspace.SessionStateProxy.SetVariable('Config', $Config)
+ $CoreRunspace.SessionStateProxy.SetVariable('Variables', $Variables)
+ $CoreRunspace.SessionStateProxy.SetVariable('Stats', $Stats)
+ $CoreRunspace.SessionStateProxy.Path.SetLocation($Variables.MainPath)
+
+ $Variables.CoreRunspace = $CoreRunspace
+
+ $PowerShell = [PowerShell]::Create()
+ $PowerShell.Runspace = $CoreRunspace
+ $PowerShell.AddScript("$($Variables.MainPath)\Includes\Core.ps1")
+ $PowerShell.BeginInvoke()
+
+ $Variables.CoreRunspace | Add-Member -Force @{ PowerShell = $PowerShell }
+
+ $Variables.Summary = "Mining processes are running."
+ Write-Host $Variables.Summary
+ }
+}
+
+Function Stop-Mining {
+
+ If ($Variables.CoreRunspace) {
+
+ If ($Variables.MiningStatus -eq "Running") { Write-Message -Level Info "Exiting cycle." }
+
+ Stop-MiningProcess
+
+ $Variables.CoreRunspace.Close()
+ If ($Variables.CoreRunspace.PowerShell) { $Variables.CoreRunspace.PowerShell.Dispose() }
+ $Variables.Remove("Timer")
+ $Variables.Remove("CoreRunspace")
+
+ $Variables.Summary = "Mining processes stopped."
+ Write-Host $Variables.Summary
+ }
+}
+
+Function Stop-MiningProcess {
+
+ If ($Variables.Miners | Where-Object ProcessID) {
+ $Variables.Summary = "Stopping mining processes..."
+ Write-Message -Level Info $Variables.Summary
+
+ # Give core loop time to shut down gracefully
+ $Timestamp = (Get-Date).AddSeconds(30)
+ While (($Variables.CoreRunspace.MiningStatus -eq "Running" -and -not $Variables.IdleRunspace) -and (Get-Date) -le $Timestamp) {
+ Start-Sleep -Seconds 1
+ }
+ $Variables.Miners | Where-Object ProcessID | ForEach-Object {
+ $_.Info = ""
+ $_.Best = $false
+ $_.SetStatus([MinerStatus]::Idle)
+ }
+ $Variables.WatchdogTimers = @()
+ }
+ $Variables.MiningStatus = "Idle"
+}
+
+Function Start-BrainJob {
+
+ Param(
+ [Parameter(Mandatory = $false)]
+ [String[]]$Jobs
+ )
+
+ # Starts Brains if necessary
+ $JobNames = @()
+
+ $Jobs | ForEach-Object {
+ If (-not $Variables.BrainJobs.$_) {
+ $BrainPath = "$($Variables.MainPath)\Brains\$(Get-PoolBaseName $_)"
+ $BrainName = "$BrainPath\Brains.ps1"
+ If (Test-Path $BrainName -PathType Leaf) {
+ $Variables.BrainJobs.$_ = Start-ThreadJob -Name "BrainJob_$($_)" -ThrottleLimit 99 -FilePath $BrainName -ArgumentList @($BrainPath, $_)
+ $JobNames += $_
+ }
+ }
+ }
+ If ($JobNames.Count -gt 0) { Write-Message -Level Verbose "Pool Brain Job$(If ($JobNames.Count -gt 1) { "s" }) for '$(($JobNames | Sort-Object) -join ", ")' running." }
+}
+
+Function Stop-BrainJob {
+
+ Param(
+ [Parameter(Mandatory = $false)]
+ [String[]]$Jobs = $Variables.BrainJobs.Keys
+ )
+
+ If ($Jobs) {
+ $JobNames = @()
+
+ # Stop Brains if necessary
+ $Jobs | ForEach-Object {
+ $Variables.BrainJobs.$_ | Stop-Job -PassThru -ErrorAction Ignore | Remove-Job -Force -ErrorAction Ignore
+ $Variables.BrainJobs.Remove($_)
+ $JobNames += $_
+ }
+
+ If ($JobNames.Count -gt 0) { Write-Message -Level Verbose "Pool Brain Job$(If ($JobNames.Count -gt 1) { "s" }) for '$(($JobNames | Sort-Object) -join ", ")' stopped." }
+ }
+}
+
+Function Start-BalancesTracker {
+
+ If (-not $Variables.BalancesTrackerRunspace) {
+
+ Try {
+ $Variables.Summary = "Starting Balances Tracker..."
+ Write-Message -Level Info $Variables.Summary
+
+ $BalancesTrackerRunspace = [runspacefactory]::CreateRunspace()
+ $BalancesTrackerRunspace.Open()
+ $BalancesTrackerRunspace.SessionStateProxy.SetVariable('Config', $Config)
+ $BalancesTrackerRunspace.SessionStateProxy.SetVariable('Variables', $Variables)
+ $BalancesTrackerRunspace.SessionStateProxy.Path.SetLocation($Variables.MainPath)
+ $PowerShell = [PowerShell]::Create()
+ $PowerShell.Runspace = $BalancesTrackerRunspace
+ $PowerShell.AddScript("$($Variables.MainPath)\Includes\BalancesTracker.ps1")
+ $PowerShell.BeginInvoke()
+
+ $Variables.BalancesTrackerRunspace = $BalancesTrackerRunspace
+ $Variables.BalancesTrackerRunspace | Add-Member -Force @{ PowerShell = $PowerShell }
+
+ Write-Host "Balances Tracker is running."
+ }
+ Catch {
+ Write-Message -Level Error "Failed to start Balances Tracker [$Error[0]]."
+ }
+ }
+}
+
+Function Stop-BalancesTracker {
+
+ If ($Variables.BalancesTrackerRunspace) {
+ $Variables.Summary += "\nStopping Balances Tracker..."
+ Write-Message -Level Info "Stopping Balances Tracker..."
+
+ $Variables.BalancesTrackerRunspace.Close()
+ If ($Variables.BalancesTrackerRunspace.PowerShell) { $Variables.BalancesTrackerRunspace.PowerShell.Dispose() }
+
+ $Variables.Remove("BalancesTrackerRunspace")
+ }
+}
+
+Function Initialize-Application {
+
+ # Keep only the last 10 files
+ Get-ChildItem -Path ".\Logs\$($Variables.Branding.ProductLabel)_*.log" -File | Sort-Object LastWriteTime | Select-Object -SkipLast 10 | Remove-Item -Force -Recurse
+ Get-ChildItem -Path ".\Logs\SwitchingLog_*.csv" -File | Sort-Object LastWriteTime | Select-Object -SkipLast 10 | Remove-Item -Force -Recurse
+ Get-ChildItem -Path "$($Variables.ConfigFile)_*.backup" -File | Sort-Object LastWriteTime | Select-Object -SkipLast 10 | Remove-Item -Force -Recurse
+
+ $Variables.ScriptStartDate = (Get-Date).ToUniversalTime()
+ If ([Net.ServicePointManager]::SecurityProtocol -notmatch [Net.SecurityProtocolType]::Tls12) { [Net.ServicePointManager]::SecurityProtocol += [Net.SecurityProtocolType]::Tls12 }
+
+ # Set process priority to BelowNormal to avoid hash rate drops on systems with weak CPUs
+ (Get-Process -Id $PID).PriorityClass = "BelowNormal"
+
+ If ($Config.Proxy -eq "") { $PSDefaultParameterValues.Remove("*:Proxy") }
+ Else { $PSDefaultParameterValues["*:Proxy"] = $Config.Proxy }
+}
+
+Function Get-DefaultAlgorithm {
+
+ # Try {
+ # $PoolsAlgos = (Invoke-WebRequest -Uri "https://nemosminer.com/data/PoolsAlgos.json" -TimeoutSec 15 -UseBasicParsing -SkipCertificateCheck -Headers @{ "Cache-Control" = "no-cache" }).Content | ConvertFrom-Json
+ # $PoolsAlgos | ConvertTo-Json | Out-File -FilePath ".\Config\PoolsAlgos.json" -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+ # }
+ # Catch {
+ If (Test-Path -Path ".\Config\PoolsAlgos.json" -PathType Leaf) {
+ $PoolsAlgos = Get-Content ".\Config\PoolsAlgos.json" | ConvertFrom-Json -ErrorAction Ignore
+ }
+ # }
+ If ($PoolsAlgos = $PoolsAlgos.PSObject.Properties | Where-Object Name -in @(Get-PoolBaseName $Config.PoolName)) { Return $PoolsAlgos.Value | Sort-Object -Unique }
+ Return
+}
+
+Function Get-CommandLineParameters {
+ Param(
+ [Parameter(Mandatory = $true)]
+ [String]$Arguments
+ )
+
+ If (Test-Json $Arguments -ErrorAction Ignore) { Return ($Arguments | ConvertFrom-Json -ErrorAction SilentlyContinue).Arguments }
+ Return $Arguments
+}
+
+Function Get-Rate {
+ # Read exchange rates from min-api.cryptocompare.com, use cached data as fallback
+
+ $RatesFile = "Cache\Rates.json"
+ $Variables.BalancesCurrencies = @($Variables.Balances.Keys | ForEach-Object { $Variables.Balances.$_.Currency } | Sort-Object -Unique)
+
+ Try {
+ If (-not $Variables.AllCurrencies -and (Test-Path -Path $RatesFile)) {
+ $Variables.AllCurrencies = @((Get-Content -Path $RatesFile -ErrorAction Ignore | ConvertFrom-Json -ErrorAction Ignore).PSObject.Properties.Name | ForEach-Object { $_ -replace '^m' } | Sort-Object -Unique )
+ }
+ Else {
+ $Variables.AllCurrencies = @((@($Config.Currency) + @($Config.Wallets.PSObject.Properties.Name) + @($Config.ExtraCurrencies) + @($Variables.BalancesCurrencies)) | Select-Object -Unique)
+ }
+ If (-not $Variables.Rates.BTC.($Config.Currency) -or (Compare-Object @($Variables.Rates.PSObject.Properties.Name | Select-Object) @($Variables.AllCurrencies | Select-Object) | Where-Object SideIndicator -eq "=>") -or ($Variables.RatesUpdated -lt (Get-Date).ToUniversalTime().AddMinutes(-(3, $Config.BalancesTrackerPollInterval | Measure-Object -Maximum).Maximum))) {
+ If ($Rates = Invoke-RestMethod "https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC&tsyms=$((@("BTC") + @($Variables.AllCurrencies | Where-Object { $_ -ne "mBTC" }) | Select-Object -Unique) -join ',')&extraParams=$($Variables.Branding.BrandWebSite)" -UseBasicParsing -TimeoutSec 5 -ErrorAction Stop | ConvertTo-Json -WarningAction SilentlyContinue | ConvertFrom-Json) {
+ $Currencies = ($Rates.BTC | Get-Member -MemberType NoteProperty -ErrorAction Ignore).Name
+ $Currencies | Where-Object { $_ -ne "BTC" } | ForEach-Object {
+ $Currency = $_
+ $Rates | Add-Member $Currency ($Rates.BTC | ConvertTo-Json -WarningAction SilentlyContinue | ConvertFrom-Json) -ErrorAction Ignore
+ ($Rates.$Currency | Get-Member -MemberType NoteProperty -ErrorAction Ignore).Name | ForEach-Object {
+ $Rates.$Currency | Add-Member $_ ([Double]$Rates.BTC.$_ / $Rates.BTC.$Currency) -Force
+ }
+ }
+ # Add mBTC
+ $Currencies | ForEach-Object {
+ $Currency = $_
+ $mCurrency = "m$($Currency)"
+ $Rates | Add-Member $mCurrency ($Rates.$Currency | ConvertTo-Json -WarningAction SilentlyContinue | ConvertFrom-Json)
+ ($Rates.$mCurrency | Get-Member -MemberType NoteProperty -ErrorAction Ignore).Name | ForEach-Object {
+ $Rates.$mCurrency | Add-Member $_ ([Double]$Rates.$Currency.$_ / 1000) -Force
+ }
+ }
+ ($Rates | Get-Member -MemberType NoteProperty -ErrorAction Ignore).Name | ForEach-Object {
+ $Currency = $_
+ ($Rates | Get-Member -MemberType NoteProperty -ErrorAction Ignore).Name | Where-Object { $_ -in $Currencies } | ForEach-Object {
+ $mCurrency = "m$($_)"
+ $Rates.$Currency | Add-Member $mCurrency ([Double]$Rates.$Currency.$_ * 1000)
+ }
+ }
+ Write-Message -Level Info "Loaded currency exchange rates from 'min-api.cryptocompare.com'."
+ $Rates | ConvertTo-Json -Depth 5 | Out-File -FilePath $RatesFile -Encoding utf8NoBOM -Force -ErrorAction SilentlyContinue
+ $Variables.Rates = $Rates
+ $Variables.RatesUpdated = (Get-Date).ToUniversalTime()
+ }
+ Else {
+ If (Test-Path -Path $RatesFile) {
+ $Variables.Rates = (Get-Content -Path $RatesFile -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop)
+ $Variables.Updated = "Cached: $((Get-Item -Path $RatesFile).CreationTime.ToUniversalTime())"
+ Write-Message -Level Warn "Could not load exchange rates from CryptoCompare. Using cached data from $((Get-Item -Path $RatesFile).CreationTime)."
+ }
+ Else {
+ Write-Message -Level Warn "Could not load exchange rates from CryptoCompare."
+ }
+ }
+ }
+ }
+ Catch {
+ If (Test-Path -Path $RatesFile) {
+ $Variables.Rates = (Get-Content -Path $RatesFile -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop)
+ $Variables.Updated = "Cached: $((Get-Item -Path $RatesFile).CreationTime.ToUniversalTime())"
+ Write-Message -Level Warn "Could not load exchange rates from CryptoCompare. Using cached data from $((Get-Item -Path $RatesFile).CreationTime)."
+ }
+ Else {
+ Write-Message -Level Warn "Could not load exchange rates from CryptoCompare."
+ }
+ }
+}
+
+Function Write-Message {
+ [CmdletBinding()]
+ Param(
+ [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
+ [ValidateNotNullOrEmpty()]
+ [String]$Message,
+ [Parameter(Mandatory = $false)]
+ [ValidateSet("Error", "Warn", "Info", "Verbose", "Debug")]
+ [String]$Level = "Info"
+ )
+
+ If ($Config.GetEnumerator() -notcontains "LogToScreen" -or $Level -in $Config.LogToScreen) {
+ # Update status text box in GUI
+ If ($Variables.LabelStatus) {
+ $Variables.LabelStatus.Lines += $Message
+
+ # Keep only 100 lines, more lines impact performance
+ $Variables.LabelStatus.Lines = @($Variables.LabelStatus.Lines | Select-Object -Last 100)
+
+ $Variables.LabelStatus.SelectionStart = $Variables.LabelStatus.TextLength
+ $Variables.LabelStatus.ScrollToCaret()
+ $Variables.LabelStatus.Refresh()
+ }
+
+ # Write to console
+ Switch ($Level) {
+ "Error" { Write-Host $Message -ForegroundColor "Red" }
+ "Warn" { Write-Host $Message -ForegroundColor "Magenta" }
+ "Info" { Write-Host $Message -ForegroundColor "White" }
+ "Verbose" { Write-Host $Message -ForegroundColor "Yello" }
+ "Debug" { Write-Host $Message -ForegroundColor "Blue" }
+ }
+ }
+
+ If ($Variables.LogFile -and $Config.LogToFile -and $Level -in $Config.LogToFile) {
+ # Get mutex. Mutexes are shared across all threads and processes.
+ # This lets us ensure only one thread is trying to write to the file at a time.
+ $Mutex = New-Object System.Threading.Mutex($false, "$($Variables.LogFile -replace '[^A-Z0-9]')")
+
+ # Attempt to aquire mutex, waiting up to 1 second if necessary. If aquired, write to the log file and release mutex. Otherwise, display an error.
+ If ($Mutex.WaitOne(1000)) {
+
+ $Date = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
+
+ "$Date $($Level.ToUpper()): $Message" | Out-File -FilePath $Variables.LogFile -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+ [void]$Mutex.ReleaseMutex()
+ }
+ Else {
+ Write-Error -Message "Log file is locked, unable to write message to $($Variables.LogFile)."
+ }
+ }
+}
+
+Function Send-MonitoringData {
+
+ # Updates a remote monitoring server, sending this worker's data and pulling data about other workers
+
+ # Skip If server and user aren't filled out
+ If (-not $Config.MonitoringServer) { Return }
+ If (-not $Config.MonitoringUser) { Return }
+
+ $Version = "$($Variables.Branding.ProductLabel) $($Variables.Branding.Version.ToString())"
+ $Status = $Variables.NewMiningStatus
+ $RunningMiners = $Variables.Miners | Where-Object { $_.Status -eq [MinerStatus]::Running }
+
+ # Build object with just the data we need to send, and make sure to use relative paths so we don't accidentally
+ # reveal someone's windows username or other system information they might not want sent
+ # For the ones that can be an array, comma separate them
+ $Data = @(
+ $RunningMiners | Sort-Object DeviceName | ForEach-Object {
+ [PSCustomObject]@{
+ Name = $_.Name
+ Path = Resolve-Path -Relative $_.Path
+ Type = $_.Type -join ','
+ Algorithm = $_.Algorithm -join ','
+ Pool = $_.WorkersRunning.Pool.Name -join ','
+ CurrentSpeed = $_.Speed_Live
+ EstimatedSpeed = $_.Workers.Speed
+ Earning = $_.Earning
+ Profit = $_.Profit
+ Currency = $Config.Currency
+ }
+ }
+ )
+
+ $Body = @{
+ user = $Config.MonitoringUser
+ worker = $Config.WorkerName
+ version = $Version
+ status = $Status
+ profit = [String][Math]::Round(($data | Measure-Object Earning -Sum).Sum, 8) # Earnings is NOT profit! Needs to be changed in mining monitor server
+ data = ConvertTo-Json $Data
+ }
+
+ # Send the request
+ Try {
+ $Response = Invoke-RestMethod -Uri "$($Config.MonitoringServer)/api/report.php" -Method Post -Body $Body -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop
+ If ($Response -eq "Success") {
+ Write-Message -Level Verbose "Reported worker status to monitoring server '$($Config.MonitoringServer)' [ID $($Config.MonitoringUser)]."
+ }
+ Else {
+ Write-Message -Level Verbose "Reporting worker status to monitoring server '$($Config.MonitoringServer)' failed: [$($Response)]."
+ }
+ }
+ Catch {
+ Write-Message -Level Warn "Monitoring: Unable to send status to '$($Config.MonitoringServer)' [ID $($Config.MonitoringUser)]."
+ }
+}
+
+Function Receive-MonitoringData {
+
+ If ($Config.ShowWorkerStatus -and $Config.MonitoringUser -and $Config.MonitoringServer) {
+ Try {
+ $Workers = Invoke-RestMethod -Uri "$($Config.MonitoringServer)/api/workers.php" -Method Post -Body @{ user = $Config.MonitoringUser } -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop
+ # Calculate some additional properties and format others
+ $Workers | ForEach-Object {
+ # Convert the unix timestamp to a datetime object, taking into account the local time zone
+ $_ | Add-Member -Force @{ date = [TimeZone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($_.lastseen)) }
+
+ # If a machine hasn't reported in for > 10 minutes, mark it as offline
+ $TimeSinceLastReport = New-TimeSpan -Start $_.date -End (Get-Date)
+ If ($TimeSinceLastReport.TotalMinutes -gt 10) { $_.status = "Offline" }
+ }
+ $Variables | Add-Member -Force @{ Workers = $Workers }
+ $Variables | Add-Member -Force @{ WorkersLastUpdated = (Get-Date) }
+
+ Remove-Variable Workers
+
+ Write-Message -Level Verbose "Retrieved worker status from '$($Config.MonitoringServer)' [ID $($Config.MonitoringUser)]."
+ }
+ Catch {
+ Write-Message -Level Warn "Monitoring: Unable to retrieve worker data from '$($Config.MonitoringServer)' [ID $($Config.MonitoringUser)]."
+ }
+ }
+}
+
+Function Merge-Hashtable {
+ Param(
+ [Parameter(Mandatory = $true)]
+ [Hashtable]$HT1,
+ [Parameter(Mandatory = $true)]
+ [Hashtable]$HT2,
+ [Parameter(Mandatory = $false)]
+ [Boolean]$Unique = $false,
+ [Parameter(Mandatory = $false)]
+ [String[]]$Replace = @() # Replace, not merge property
+ )
+
+ $HT2.Keys | ForEach-Object {
+ If ($HT1.$_ -is [Hashtable]) {
+ $HT1.$_ = Merge-Hashtable -HT1 $HT1.$_ -Ht2 $HT2.$_ -Unique $Unique -replace $Replace
+ }
+ ElseIf ($HT1.$_ -is [Array] -and $_ -notin $NoMerge) {
+ $HT1.$_ += $HT2.$_
+ If ($Unique) { $HT1.$_ = $HT1.$_ | Sort-Object -Unique }
+ }
+ ElseIf ($HT2.$_) {
+ $HT1.$_ = $HT2.$_
+ }
+ }
+ $HT1
+}
+
+Function Get-DonationPoolConfig {
+ # Randomize donation data
+ # Build pool config with available donation data, not all devs have the same set of wallets available
+
+ $Variables.DonateRandom = $Variables.DonationData | Get-Random
+ $Variables.DonatePoolsConfig = [Ordered]@{ }
+ (Get-ChildItem .\Pools\*.ps1 -File).BaseName | Sort-Object -Unique | ForEach-Object {
+ $PoolConfig = @{ }
+ $PoolConfig.EarningsAdjustmentFactor = 1
+ $PoolConfig.Region = $Config.PoolsConfig.$_.Region
+ $PoolConfig.WorkerName = "$($Variables.Branding.ProductLabel)-$($Variables.Branding.Version.ToString())-donate$($Config.Donate)"
+ Switch -regex ($_) {
+ "^MiningPoolHub$|^ProHashing$" {
+ If ($Variables.DonateRandom."$($_)UserName") { # not all devs have a known ProHashing account
+ $PoolConfig.UserName = $Variables.DonateRandom."$($_)UserName"
+ $PoolConfig.Variant = $Config.PoolsConfig.$_.Variant
+ $Variables.DonatePoolsConfig.$_ = $PoolConfig
+ }
+ Break
+ }
+ Default {
+ If ($Variables.DonateRandom.Wallets) {
+ # not all devs have a known ETC or ETH address
+ If ($Config.PoolName -match $_ -and (Compare-Object @($Variables.PoolData.$_.GuaranteedPayoutCurrencies) @($Variables.DonateRandom.Wallets.PSObject.Properties.Name) -IncludeEqual -ExcludeDifferent)) {
+ $PoolConfig.Variant = If ($Config.PoolsConfig.$_.Variant) { $Config.PoolsConfig.$_.Variant } Else { $Config.PoolName -match $_ }
+ $PoolConfig.Wallets = $Variables.DonateRandom.Wallets | ConvertTo-Json | ConvertFrom-Json -AsHashtable
+ $Variables.DonatePoolsConfig.$_ = $PoolConfig
+ }
+ }
+ Break
+ }
+ }
+ }
+}
+
+Function Read-Config {
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [String]$ConfigFile
+ )
+
+ # Load the configuration
+ If (Test-Path -PathType Leaf $ConfigFile) {
+ $Config_Tmp = Get-Content $ConfigFile | ConvertFrom-Json -ErrorAction Ignore | Select-Object
+ If ($Config_Tmp.PSObject.Properties.Count -eq 0 -or $Config_Tmp -isnot [PSCustomObject]) {
+ Copy-Item -Path $ConfigFile "$($ConfigFile).corrupt" -Force
+ Write-Message -Level Warn "Configuration file '$($ConfigFile)' is corrupt."
+ $Config.ConfigFileVersionCompatibility = $null
+ }
+ Else {
+ # Fix upper / lower case (Web GUI is case sensitive)
+ $Config_Tmp.PSObject.Properties.Name | ForEach-Object {
+ $Config.Remove($_)
+ $Config.$_ = $Config_Tmp.$_
+ }
+ }
+ Remove-Variable Config_Tmp
+ }
+ Else {
+ Write-Message -Level Warn "No valid configuration file found."
+
+ $Variables.FreshConfig = $true
+ If (Test-Path -Path ".\Data\PoolsConfig-Recommended.json" -PathType Leaf) {
+ # Add default enabled pools
+ $Temp = (Get-Content ".\Data\PoolsConfig-Recommended.json" -ErrorAction Ignore | ConvertFrom-Json -ErrorAction Ignore)
+ $Config.PoolName = $Temp.PSObject.Properties.Name | Where-Object { $_ -ne "Default" } | ForEach-Object { $Temp.$_.Variant.PSObject.Properties.Name }
+ Remove-Variable Temp
+ }
+
+ # Add config items
+ $Variables.AllCommandLineParameters.Keys | Where-Object { $_ -notin $Config.Keys } | Sort-Object | ForEach-Object {
+ $Value = $Variables.AllCommandLineParameters.$_
+ If ($Value -is [Switch]) { $Value = [Boolean]$Value }
+ $Config.$_ = $Value
+ }
+
+ # MinerInstancePerDeviceModel: Default to $true if more than one device model per vendor
+ $Config.MinerInstancePerDeviceModel = ($Variables.Devices | Group-Object Vendor | ForEach-Object { ($_.Group.Model | Sort-Object -Unique).Count } | Measure-Object -Maximum).Maximum -gt 1
+
+ $Config.ConfigFileVersion = $Variables.Branding.Version.ToString()
+ }
+
+ # Ensure parameter format
+ $Variables.AllCommandLineParameters.Keys | ForEach-Object {
+ If ($Variables.AllCommandLineParameters.$_ -is [Array] -and $Config.$_ -isnot [Array]) { $Config.$_ = @($Config.$_ -replace " " -split ",") } # Enforce array
+ }
+
+ $DefaultPoolData = $Variables.PoolData
+
+ # Build custom pools configuration, create case insensitive hashtable (https://stackoverflow.com/questions/24054147/powershell-hash-tables-double-key-error-a-and-a)
+ If ($Variables.PoolsConfigFile -and (Test-Path -PathType Leaf $Variables.PoolsConfigFile)) {
+ $CustomPoolsConfig = [Ordered]@{ }
+ Try {
+ $Temp = (Get-Content $Variables.PoolsConfigFile -ErrorAction Ignore | ConvertFrom-Json -NoEnumerate -AsHashTable -ErrorAction Ignore)
+ $Temp.Keys | Sort-Object | ForEach-Object { $CustomPoolsConfig += @{ $_ = $Temp.$_ } }
+ $Variables.PoolsConfigData = $CustomPoolsConfig
+ }
+ Catch {
+ Write-Message -Level Warn "Pools configuration file '$($Variables.PoolsConfigFile)' is corrupt and will be ignored."
+ }
+ }
+
+ # Build in memory pool config
+ $PoolsConfig = [Ordered]@{ }
+ (Get-PoolBasename $Config.PoolName) -replace " Internal$| External$" | ForEach-Object {
+ $PoolName = $_
+ If ($PoolConfig = $DefaultPoolData.$PoolName) {
+ # Merge default pool data with custom pool config
+ If ($CustomPoolConfig = $CustomPoolsConfig.$PoolName) { $PoolConfig = Merge-Hashtable -HT1 $PoolConfig -HT2 $CustomPoolConfig -Unique $true }
+
+ If (-not $PoolConfig.EarningsAdjustmentFactor) { $PoolConfig.EarningsAdjustmentFactor = $Config.EarningsAdjustmentFactor }
+ If (-not $PoolConfig.WorkerName) { $PoolConfig.WorkerName = $Config.WorkerName }
+ If (-not $PoolConfig.BalancesKeepAlive) { $PoolConfig.BalancesKeepAlive = $PoolData.$PoolName.BalancesKeepAlive }
+
+ Switch ($PoolName) {
+ "HiveON" {
+ If (-not $PoolConfig.Wallets) {
+ $PoolConfig.Wallets = [PSCustomObject]@{ }
+ ($Config.Wallets | Get-Member -MemberType NoteProperty -ErrorAction Ignore).Name | Where-Object { $_ -in $PoolConfig.PayoutCurrencies } | ForEach-Object {
+ $PoolConfig.Wallets | Add-Member $_ ($Config.Wallets.$_)
+ }
+ }
+ }
+ "MiningPoolHub" {
+ If (-not $PoolConfig.UserName) { $PoolConfig.UserName = $Config.MiningPoolHubUserName }
+ }
+ "NiceHash" {
+ If (-not $PoolConfig.Variant."Nicehash Internal".Wallets.BTC) {
+ If ($Config.NiceHashWallet -and $Config.NiceHashWalletIsInternal) { $PoolConfig.Variant."NiceHash Internal".Wallets = @{ "BTC" = $Config.NiceHashWallet } }
+ }
+ If (-not $PoolConfig.Variant."Nicehash External".Wallets.BTC) {
+ If ($Config.NiceHashWallet -and -not $Config.NiceHashWalletIsInternal) { $PoolConfig.Variant."NiceHash External".Wallets = @{ "BTC" = $Config.NiceHashWallet } }
+ ElseIf ($Config.Wallets.BTC) { $PoolConfig.Variant."NiceHash External".Wallets = @{ "BTC" = $Config.Wallets.BTC } }
+ }
+ }
+ "ProHashing" {
+ If (-not $PoolConfig.UserName) { $PoolConfig.UserName = $Config.ProHashingUserName }
+ If (-not $PoolConfig.MiningMode) { $PoolConfig.MiningMode = $Config.ProHashingMiningMode }
+ }
+ Default {
+ If ((-not $PoolConfig.PayoutCurrency) -or $PoolConfig.PayoutCurrency -eq "[Default]") { $PoolConfig.PayoutCurrency = $Config.PayoutCurrency }
+ If (-not $PoolConfig.Wallets) { $PoolConfig.Wallets = @{ "$($PoolConfig.PayoutCurrency)" = $($Config.Wallets.($PoolConfig.PayoutCurrency)) } }
+ $PoolConfig.Remove("PayoutCurrency")
+ }
+ }
+ If ($PoolConfig.EarningsAdjustmentFactor -le 0 -or $PoolConfig.EarningsAdjustmentFactor -gt 1) { $PoolConfig.EarningsAdjustmentFactor = 1 }
+ If ($PoolConfig.Algorithm) { $PoolConfig.Algorithm = @($PoolConfig.Algorithm -replace " " -split ",") }
+ }
+ $PoolsConfig.$PoolName = $PoolConfig
+ }
+ $Config.PoolsConfig = $PoolsConfig
+}
+
+Function Write-Config {
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [String]$ConfigFile,
+ [Parameter(Mandatory = $false)]
+ [PSCustomObject]$NewConfig = $Config
+ )
+
+ $Header =
+"// This file was initially generated by $($Variables.Branding.ProductLabel)
+// It should still be usable in newer versions, but newer versions might have additional
+// settings or changes
+
+// $($Variables.Branding.ProductLabel) will automatically add / convert / rename / update new settings when updating to a new version
+"
+ If (Test-Path $ConfigFile -PathType Leaf) {
+ Copy-Item -Path $ConfigFile -Destination "$($ConfigFile)_$(Get-Date -Format "yyyy-MM-dd_HH-mm-ss").backup"
+ Get-ChildItem -Path "$($ConfigFile)_*.backup" -File | Sort-Object LastWriteTime | Select-Object -SkipLast 10 | Remove-Item -Force -Recurse # Keep 10 backup copies
+ }
+
+ $SortedConfig = $NewConfig | Get-SortedObject
+ $ConfigTmp = [Ordered]@{ }
+ $SortedConfig.Keys | Where-Object { $_ -notin @("ConfigFile", "PoolsConfig") } | ForEach-Object {
+ $ConfigTmp[$_] = $SortedConfig.$_
+ }
+ "$Header$($ConfigTmp | ConvertTo-Json -Depth 10)" | Out-File -FilePath $ConfigFile -Force -Encoding utf8NoBOM -ErrorAction Ignore
+}
+Function Edit-File {
+
+ # Opens file in notepad. Notepad will remain in foreground until notepad is closed.
+
+ Param(
+ [Parameter(Mandatory = $false)]
+ [String]$FileName
+ )
+
+ $FileWriteTime = (Get-Item -Path $FileName -ErrorAction Ignore).LastWriteTime
+
+ If (-not ($NotepadProcess = (Get-CimInstance CIM_Process | Where-Object CommandLine -Like "*\Notepad.exe* $($FileName)"))) {
+ Notepad.exe $FileName
+ }
+ If ($NotepadProcess = (Get-CimInstance CIM_Process | Where-Object CommandLine -Like "*\Notepad.exe* $($FileName)")) {
+ # Check if the window is not already in foreground
+ While ($NotepadProcess = (Get-CimInstance CIM_Process | Where-Object CommandLine -Like "*\Notepad.exe* $($FileName)")) {
+ $FGWindowPid = [IntPtr]::Zero
+ [Void][Win32]::GetWindowThreadProcessId([Win32]::GetForegroundWindow(), [ref]$FGWindowPid)
+ $MainWindowHandle = (Get-Process -Id $NotepadProcess.ProcessId).MainWindowHandle
+ If ($NotepadProcess.ProcessId -ne $FGWindowPid) {
+ If ([Win32]::GetForegroundWindow() -ne $MainWindowHandle) {
+ [Void][Win32]::ShowWindowAsync($MainWindowHandle, 6) # SW_MINIMIZE
+ [Void][Win32]::ShowWindowAsync($MainWindowHandle, 9) # SW_RESTORE
+ }
+ }
+ Start-Sleep -MilliSeconds 100
+ }
+ }
+
+ If ($FileWriteTime -ne (Get-Item -Path $FileName -ErrorAction Ignore).LastWriteTime) {
+ Write-Message -Level Verbose "Saved '$(($FileName))'. Changes will become active in next cycle."
+ Return "Saved '$(($FileName))'`nChanges will become active in next cycle."
+ }
+ Else {
+ Return "No changes to '$(($FileName))' made."
+ }
+}
+
+Function Get-SortedObject {
+
+ Param (
+ [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
+ [Object]$Object
+ )
+
+ $Object = $Object | ConvertTo-Json -Depth 20 | ConvertFrom-Json -NoEnumerate -ErrorAction Ignore
+
+ # Build an ordered hashtable of the property-value pairs.
+ $SortedObject = [Ordered]@{ }
+
+ Switch -Regex ($Object.GetType().Name) {
+ "PSCustomObject" {
+ Get-Member -Type NoteProperty -InputObject $Object | Sort-Object Name | ForEach-Object {
+ # Upper / lower case conversion (Web GUI is case sensitive)
+ $Property = $_.Name
+ $Property = $Variables.AvailableCommandLineParameters | Where-Object { $_ -eq $Property }
+ If (-not $PropertyName) { $Property = $_.Name }
+
+ If ($Object.$Property -is [Hashtable] -or $Object.$Property -is [PSCustomObject]) { $SortedObject[$Property] = Get-SortedObject $Object.$Property }
+ ElseIf ($Object.$Property -is [Array]) { $SortedObject[$Property] = $Object.$Property -as $Object.$Property.GetType().Name }
+ Else { $SortedObject[$Property] = $Object.$Property }
+ }
+ }
+ "Hashtable|SyncHashtable" {
+ $Object.Keys | Sort-Object | ForEach-Object {
+ # Upper / lower case conversion (Web GUI is case sensitive)
+ $Key = $_
+ $Key = $Variables.AvailableCommandLineParameters | Where-Object { $_ -eq $Key }
+ If (-not $Key) { $Key = $_ }
+
+ $SortedObject[$Key] = If ($Object.$Key -is [Hashtable] -or $Object.$Key -is [PSCustomObject]) { Get-SortedObject $Object.$Key } Else { $Object.$Key }
+ }
+ }
+ Default {
+ $SortedObject = $Object
+ }
+ }
+
+ $SortedObject
+}
+
+Function Set-Stat {
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [String]$Name,
+ [Parameter(Mandatory = $true)]
+ [Double]$Value,
+ [Parameter(Mandatory = $false)]
+ [DateTime]$Updated = (Get-Date),
+ [Parameter(Mandatory = $false)]
+ [TimeSpan]$Duration,
+ [Parameter(Mandatory = $false)]
+ [Boolean]$FaultDetection = $true,
+ [Parameter(Mandatory = $false)]
+ [Boolean]$ChangeDetection = $false,
+ [Parameter(Mandatory = $false)]
+ [Int]$ToleranceExceeded = 3
+ )
+
+ $Timer = $Updated = $Updated.ToUniversalTime()
+
+ $Path = "Stats\$Name.txt"
+ $SmallestValue = 1E-20
+ $Disabled = $Value -eq -1
+ $Stat = Get-Stat -Name $Name
+
+ If ($Stat -is [Hashtable] -and $Stat.IsSynchronized -and -not [Double]::IsNaN($Stat.Minute_Fluctuation)) {
+ If (-not $Stat.Timer) { $Stat.Timer = $Stat.Updated.AddMinutes(-1) }
+ If (-not $Duration) { $Duration = $Updated - $Stat.Timer }
+ If ($Duration -le 0) { Return $Stat }
+
+ If ($Disabled) { $Value = [Decimal]$Stat.Live }
+
+ If ($ChangeDetection -and [Decimal]$Value -eq [Decimal]$Stat.Live) { $Updated = $Stat.Updated }
+
+ If ($FaultDetection) {
+ $FaultFactor = If ($Name -match ".+_Hashrate$") { 0.1 } Else { 0.2 }
+ $ToleranceMin = $Stat.Week * (1 - $FaultFactor)
+ $ToleranceMax = $Stat.Week * (1 + $FaultFactor)
+ }
+ Else {
+ $ToleranceMin = $ToleranceMax = $Value
+ }
+
+ If ($Value -lt $ToleranceMin -or $Value -gt $ToleranceMax) { $Stat.ToleranceExceeded ++ }
+ Else { $Stat | Add-Member ToleranceExceeded ([UInt16]0) -Force }
+
+ If ($Value -gt 0 -and $Stat.ToleranceExceeded -gt 0 -and $Stat.ToleranceExceeded -lt $ToleranceExceeded -and $Stat.Week -gt 0) {
+ If ($Name -match ".+_Hashrate$") {
+ Write-Message -Level Warn "Error saving hash rate for '$($Name -replace '_Hashrate$')'. $(($Value | ConvertTo-Hash) -replace '\s+', '') is outside fault tolerance ($(($ToleranceMin | ConvertTo-Hash) -replace '\s+', ' ') to $(($ToleranceMax | ConvertTo-Hash) -replace '\s+', ' ')) [Iteration $($Stats.($Stat.Name).ToleranceExceeded) of $ToleranceExceeded until enforced update]."
+ }
+ ElseIf ($Name -match ".+_PowerUsage") {
+ Write-Message -Level Warn "Error saving power usage for '$($Name -replace '_PowerUsage$')'. $($Value.ToString("N2"))W is outside fault tolerance ($($ToleranceMin.ToString("N2"))W to $($ToleranceMax.ToString("N2"))W) [Iteration $($Stats.($Stat.Name).ToleranceExceeded) of $ToleranceExceeded until enforced update]."
+ }
+ Return
+ }
+ Else {
+ If ($Value -eq 0 -or $Stat.ToleranceExceeded -ge $ToleranceExceeded -or $Stat.Week_Fluctuation -ge 1) {
+ If ($Value -gt 0 -and $Stat.ToleranceExceeded -ge $ToleranceExceeded) {
+ If ($Name -match ".+_Hashrate$") {
+ Write-Message -Level Warn "Hashrate '$($Name -replace '_Hashrate$')' was forcefully updated. $(($Value | ConvertTo-Hash) -replace '\s+', ' ') was outside fault tolerance ($(($ToleranceMin | ConvertTo-Hash) -replace '\s+', ' ') to $(($ToleranceMax | ConvertTo-Hash) -replace '\s+', ' '))$(If ($Stat.Week_Fluctuation -lt 1) { " for $($Stats.($Stat.Name).ToleranceExceeded) times in a row." })"
+ }
+ ElseIf ($Name -match ".+_PowerUsage$") {
+ Write-Message -Level Warn "Power usage for '$($Name -replace '_PowerUsage$')' was forcefully updated. $($Value.ToString("N2"))W was outside fault tolerance ($($ToleranceMin.ToString("N2"))W to $($ToleranceMax.ToString("N2"))W)$(If ($Stat.Week_Fluctuation -lt 1) { " for $($Stats.($Stat.Name).ToleranceExceeded) times in a row." })"
+ }
+ }
+
+ Remove-Stat -Name $Name
+ $Stat = Set-Stat -Name $Name -Value $Value
+ }
+ Else {
+ $Span_Minute = [Math]::Min($Duration.TotalMinutes / [Math]::Min($Stat.Duration.TotalMinutes, 1), 1)
+ $Span_Minute_5 = [Math]::Min(($Duration.TotalMinutes / 5) / [Math]::Min(($Stat.Duration.TotalMinutes / 5), 1), 1)
+ $Span_Minute_10 = [Math]::Min(($Duration.TotalMinutes / 10) / [Math]::Min(($Stat.Duration.TotalMinutes / 10), 1), 1)
+ $Span_Hour = [Math]::Min($Duration.TotalHours / [Math]::Min($Stat.Duration.TotalHours, 1), 1)
+ $Span_Day = [Math]::Min($Duration.TotalDays / [Math]::Min($Stat.Duration.TotalDays, 1), 1)
+ $Span_Week = [Math]::Min(($Duration.TotalDays / 7) / [Math]::Min(($Stat.Duration.TotalDays / 7), 1), 1)
+
+ $Stat.Name = $Name
+ $Stat.Live = $Value
+ $Stat.Minute_Fluctuation = ((1 - $Span_Minute) * $Stat.Minute_Fluctuation) + ($Span_Minute * ([Math]::Abs($Value - $Stat.Minute) / [Math]::Max([Math]::Abs($Stat.Minute), $SmallestValue)))
+ $Stat.Minute = ((1 - $Span_Minute) * $Stat.Minute) + ($Span_Minute * $Value)
+ $Stat.Minute_5_Fluctuation = ((1 - $Span_Minute_5) * $Stat.Minute_5_Fluctuation) + ($Span_Minute_5 * ([Math]::Abs($Value - $Stat.Minute_5) / [Math]::Max([Math]::Abs($Stat.Minute_5), $SmallestValue)))
+ $Stat.Minute_5 = ((1 - $Span_Minute_5) * $Stat.Minute_5) + ($Span_Minute_5 * $Value)
+ $Stat.Minute_10_Fluctuation = ((1 - $Span_Minute_10) * $Stat.Minute_10_Fluctuation) + ($Span_Minute_10 * ([Math]::Abs($Value - $Stat.Minute_10) / [Math]::Max([Math]::Abs($Stat.Minute_10), $SmallestValue)))
+ $Stat.Minute_10 = ((1 - $Span_Minute_10) * $Stat.Minute_10) + ($Span_Minute_10 * $Value)
+ $Stat.Hour_Fluctuation = ((1 - $Span_Hour) * $Stat.Hour_Fluctuation) + ($Span_Hour * ([Math]::Abs($Value - $Stat.Hour) / [Math]::Max([Math]::Abs($Stat.Hour), $SmallestValue)))
+ $Stat.Hour = ((1 - $Span_Hour) * $Stat.Hour) + ($Span_Hour * $Value)
+ $Stat.Day_Fluctuation = ((1 - $Span_Day) * $Stat.Day_Fluctuation) + ($Span_Day * ([Math]::Abs($Value - $Stat.Day) / [Math]::Max([Math]::Abs($Stat.Day), $SmallestValue)))
+ $Stat.Day = ((1 - $Span_Day) * $Stat.Day) + ($Span_Day * $Value)
+ $Stat.Week_Fluctuation = ((1 - $Span_Week) * $Stat.Week_Fluctuation) + ($Span_Week * ([Math]::Abs($Value - $Stat.Week) / [Math]::Max([Math]::Abs($Stat.Week), $SmallestValue)))
+ $Stat.Week = ((1 - $Span_Week) * $Stat.Week) + ($Span_Week * $Value)
+ $Stat.Duration = $Stat.Duration + $Duration
+ $Stat.Updated = $Updated
+ $Stat.Disabled = $Disabled
+ $Stat.Timer = $Timer
+ $Stat.ToleranceExceeded = [UInt16]0
+ }
+ }
+ }
+ Else {
+ If (-not $Duration) { $Duration = [TimeSpan]::FromMinutes(1) }
+
+ $Global:Stats.$Name = $Stat = [Hashtable]::Synchronized(
+ @{
+ Name = [String]$Name
+ Live = [Double]$Value
+ Minute = [Double]$Value
+ Minute_Fluctuation = [Double]0
+ Minute_5 = [Double]$Value
+ Minute_5_Fluctuation = [Double]0
+ Minute_10 = [Double]$Value
+ Minute_10_Fluctuation = [Double]0
+ Hour = [Double]$Value
+ Hour_Fluctuation = [Double]0
+ Day = [Double]$Value
+ Day_Fluctuation = [Double]0
+ Week = [Double]$Value
+ Week_Fluctuation = [Double]0
+ Duration = [TimeSpan]$Duration
+ Updated = [DateTime]$Updated
+ Disabled = [Boolean]$Disabled
+ ToleranceExceeded = [UInt16]0
+ Timer = [DateTime]$Timer
+ }
+ )
+ }
+
+ @{
+ Live = [Double]$Stat.Live
+ Minute = [Double]$Stat.Minute
+ Minute_Fluctuation = [Double]$Stat.Minute_Fluctuation
+ Minute_5 = [Double]$Stat.Minute_5
+ Minute_5_Fluctuation = [Double]$Stat.Minute_5_Fluctuation
+ Minute_10 = [Double]$Stat.Minute_10
+ Minute_10_Fluctuation = [Double]$Stat.Minute_10_Fluctuation
+ Hour = [Double]$Stat.Hour
+ Hour_Fluctuation = [Double]$Stat.Hour_Fluctuation
+ Day = [Double]$Stat.Day
+ Day_Fluctuation = [Double]$Stat.Day_Fluctuation
+ Week = [Double]$Stat.Week
+ Week_Fluctuation = [Double]$Stat.Week_Fluctuation
+ Duration = [String]$Stat.Duration
+ Updated = [DateTime]$Stat.Updated
+ Disabled = [Boolean]$Stat.Disabled
+ } | ConvertTo-Json | Out-File -FilePath $Path -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+
+ $Stat
+}
+
+Function Get-Stat {
+
+ Param(
+ [Parameter(Mandatory = $false)]
+ [String[]]$Name = (
+ & {
+ [String[]]$StatFiles = ((Get-ChildItem -Path "Stats" -File -ErrorAction Ignore).BaseName | Sort-Object -Unique)
+ ($Global:Stats.Keys | Select-Object | Where-Object { $_ -notin $StatFiles }) | ForEach-Object { $Global:Stats.Remove($_) } # Remove stat if deleted on disk
+ $StatFiles
+ }
+ )
+ )
+
+ If ($Global:Stats -isnot [Hashtable] -or -not $Global:Stats.IsSynchronized) {
+ $Global:Stats = [Hashtable]::Synchronized(@{ })
+ }
+
+ $Name | ForEach-Object {
+ $Stat_Name = $_
+
+ If ($Stats.$Stat_Name -isnot [Hashtable] -or -not $Global:Stats.$Stat_Name.IsSynchronized) {
+ # Reduce number of errors
+ If (-not (Test-Path -Path "Stats\$Stat_Name.txt" -PathType Leaf)) {
+ If (-not (Test-Path -Path "Stats" -PathType Container)) {
+ New-Item "Stats" -ItemType "directory" -Force | Out-Null
+ }
+ Return
+ }
+
+ Try {
+ $Stat = Get-Content "Stats\$Stat_Name.txt" -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop
+ $Global:Stats.$Stat_Name = [Hashtable]::Synchronized(
+ @{
+ Name = [String]$Stat_Name
+ Live = [Double]$Stat.Live
+ Minute = [Double]$Stat.Minute
+ Minute_Fluctuation = [Double]$Stat.Minute_Fluctuation
+ Minute_5 = [Double]$Stat.Minute_5
+ Minute_5_Fluctuation = [Double]$Stat.Minute_5_Fluctuation
+ Minute_10 = [Double]$Stat.Minute_10
+ Minute_10_Fluctuation = [Double]$Stat.Minute_10_Fluctuation
+ Hour = [Double]$Stat.Hour
+ Hour_Fluctuation = [Double]$Stat.Hour_Fluctuation
+ Day = [Double]$Stat.Day
+ Day_Fluctuation = [Double]$Stat.Day_Fluctuation
+ Week = [Double]$Stat.Week
+ Week_Fluctuation = [Double]$Stat.Week_Fluctuation
+ Duration = [TimeSpan]$Stat.Duration
+ Updated = [DateTime]$Stat.Updated
+ Disabled = [Boolean]$Stat.Disabled
+ ToleranceExceeded = [UInt16]0
+ }
+ )
+ }
+ Catch {
+ Write-Message -Level Warn "Stat file ($Stat_Name) is corrupt and will be reset."
+ Remove-Stat $Stat_Name
+ }
+ }
+
+ $Global:Stats.$Stat_Name
+ }
+}
+
+Function Remove-Stat {
+
+ Param(
+ [Parameter(Mandatory = $false)]
+ [String[]]$Name = @($Global:Stats.Keys | Select-Object) + @((Get-ChildItem -Path "Stats" -Directory -ErrorAction Ignore ).BaseName)
+ )
+
+ $Name | Sort-Object -Unique | ForEach-Object {
+ Remove-Item -Path "Stats\$_.txt" -Force -Confirm:$false -ErrorAction SilentlyContinue
+ If ($Global:Stats.$_) { $Global:Stats.Remove($_) }
+ }
+}
+
+Function Get-ArgumentsPerDevice {
+
+ # filters the arguments to contain only argument values for selected devices
+ # if an argument has multiple values, only the values for the available devices are included
+ # arguments with a single value are valid for all devices and remain untouched
+ # excluded arguments are passed unmodified
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [AllowEmptyString()]
+ [String]$Arguments,
+ [Parameter(Mandatory = $false)]
+ [String[]]$ExcludeArguments = "",
+ [Parameter(Mandatory = $false)]
+ [Int[]]$DeviceIDs
+ )
+
+ $ArgumentsPerDevice = ""
+
+ " $($Arguments.TrimStart().TrimEnd())" -split "(?=\s+[-]{1,2})" | ForEach-Object {
+ $Token = $_
+ $Prefix = ""
+ $ParameterSeparator = ""
+ $ValueSeparator = ""
+ $Values = ""
+
+ If ($Token -match "(?:^\s[-=]+)" <#supported prefix characters are listed in brackets [-=]#>) {
+ $Prefix = $Matches[0]
+ $Token = $Token -split $Matches[0] | Select-Object -Last 1
+
+ If ($Token -match "(?:[ =]+)" <#supported separators are listed in brackets [ =]#>) {
+ $ParameterSeparator = $Matches[0]
+ $Parameter = $Token -split $ParameterSeparator | Select-Object -First 1
+ $Values = $Token.Substring(("$Parameter$($ParameterSeparator)").length)
+
+ If ($Parameter -notin $ExcludeArguments -and $Values -match "(?:[,; ]{1})" <#supported separators are listed in brackets [,; ]#>) {
+ $ValueSeparator = $Matches[0]
+ $RelevantValues = @()
+ $DeviceIDs | ForEach-Object {
+ $RelevantValues += ($Values.Split($ValueSeparator) | Select-Object -Index $_)
+ }
+ $ArgumentsPerDevice += "$Prefix$Parameter$ParameterSeparator$($RelevantValues -join $ValueSeparator)"
+ }
+ Else { $ArgumentsPerDevice += "$Prefix$Parameter$ParameterSeparator$Values" }
+ }
+ Else { $ArgumentsPerDevice += "$Prefix$Token" }
+ }
+ Else { $ArgumentsPerDevice += $Token }
+ }
+ $ArgumentsPerDevice
+}
+
+Function Get-ChildItemContent {
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [String]$Path,
+ [Parameter(Mandatory = $false)]
+ [Hashtable]$Parameters = @{ },
+ [Parameter(Mandatory = $false)]
+ [Switch]$Threaded = $false,
+ [Parameter(Mandatory = $false)]
+ [String]$Priority
+ )
+
+ If ($Priority) { ([System.Diagnostics.Process]::GetCurrentProcess()).PriorityClass = $Priority } Else { $Priority = ([System.Diagnostics.Process]::GetCurrentProcess()).PriorityClass }
+
+ $ScriptBlock = {
+ Param(
+ [Parameter(Mandatory = $true)]
+ [String]$Path,
+ [Parameter(Mandatory = $false)]
+ [Hashtable]$Parameters = @{ },
+ [Parameter(Mandatory = $false)]
+ [String]$Priority = "BelowNormal"
+ )
+
+ ([System.Diagnostics.Process]::GetCurrentProcess()).PriorityClass = $Priority
+
+ Function Invoke-ExpressionRecursive ($Expression) {
+ If ($Expression -is [String]) {
+ If ($Expression -match '\$') {
+ Try { $Expression = Invoke-Expression $Expression }
+ Catch { $Expression = Invoke-Expression "`"$Expression`"" }
+ }
+ }
+ ElseIf ($Expression -is [PSCustomObject]) {
+ $Expression.PSObject.Properties.Name | ForEach-Object {
+ $Expression.$_ = Invoke-ExpressionRecursive $Expression.$_
+ }
+ }
+ Return $Expression
+ }
+
+ Get-ChildItem -Path $Path -File -ErrorAction SilentlyContinue | ForEach-Object {
+ $Name = $_.BaseName
+ $Content = @()
+ If ($_.Extension -eq ".ps1") {
+ $Content = & {
+ $Parameters.Keys | ForEach-Object { Set-Variable $_ $Parameters.$_ }
+ & $_.FullName @Parameters
+ }
+ }
+ Else {
+ $Content = & {
+ $Parameters.Keys | ForEach-Object { Set-Variable $_ $Parameters.$_ }
+ Try {
+ ($_ | Get-Content | ConvertFrom-Json) | ForEach-Object { Invoke-ExpressionRecursive $_ }
+ }
+ Catch [ArgumentException] {
+ $null
+ }
+ }
+ If ($null -eq $Content) { $Content = $_ | Get-Content }
+ }
+ $Content | ForEach-Object {
+ [PSCustomObject]@{ Name = $Name; Content = $_ }
+ }
+ }
+ }
+
+ If ($Threaded) {
+ Return (Start-ThreadJob -Name "Get-ChildItemContent_$($Path -replace '\.\\|\.\*' -replace '\\', '_')" -ThrottleLimit 99 -ScriptBlock $ScriptBlock -ArgumentList $Path, $Parameters, $Priority)
+ }
+ Else {
+ Return (& $ScriptBlock -Path $Path -Parameters $Parameters)
+ }
+}
+
+Function Invoke-TcpRequest {
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [String]$Server,
+ [Parameter(Mandatory = $true)]
+ [String]$Port,
+ [Parameter(Mandatory = $true)]
+ [String]$Request,
+ [Parameter(Mandatory = $true)]
+ [Int]$Timeout, # seconds
+ [Parameter(Mandatory = $false)]
+ [Boolean]$ReadToEnd = $false
+ )
+
+ Try {
+ $Client = [Net.Sockets.TcpClient]::new($Server, $Port)
+ $Client.SendTimeout = $Client.ReceiveTimeout = $Timeout * 1000
+ $Stream = $Client.GetStream()
+ $Writer = [IO.StreamWriter]::new($Stream)
+ $Reader = [IO.StreamReader]::new($Stream)
+ $Writer.AutoFlush = $true
+ $Writer.WriteLine($Request)
+ $Response = If ($ReadToEnd) { $Reader.ReadToEnd() } Else { $Reader.ReadLine() }
+ }
+ Catch { $Error.Remove($error[$Error.Count - 1]) }
+ Finally {
+ If ($Reader) { $Reader.Close() }
+ If ($Writer) { $Writer.Close() }
+ If ($Stream) { $Stream.Close() }
+ If ($Client) { $Client.Close() }
+ }
+
+ $Response
+}
+
+Function Get-CpuId {
+
+ # Brief : gets CPUID (CPU name and registers)
+
+ # OS Features
+ # $OS_x64 = "" # not implemented
+ # $OS_AVX = "" # not implemented
+ # $OS_AVX512 = "" # not implemented
+
+ # Vendor
+ $vendor = "" # not implemented
+
+ $info = [CpuID]::Invoke(0)
+ # convert 16 bytes to 4 ints for compatibility with existing code
+ $info = [Int[]]@(
+ [BitConverter]::ToInt32($info, 0 * 4)
+ [BitConverter]::ToInt32($info, 1 * 4)
+ [BitConverter]::ToInt32($info, 2 * 4)
+ [BitConverter]::ToInt32($info, 3 * 4)
+ )
+
+ $nIds = $info[0]
+
+ $info = [CpuID]::Invoke(0x80000000)
+ $nExIds = [BitConverter]::ToUInt32($info, 0 * 4) # not sure as to why 'nExIds' is unsigned; may not be necessary
+ # convert 16 bytes to 4 ints for compatibility with existing code
+ $info = [Int[]]@(
+ [BitConverter]::ToInt32($info, 0 * 4)
+ [BitConverter]::ToInt32($info, 1 * 4)
+ [BitConverter]::ToInt32($info, 2 * 4)
+ [BitConverter]::ToInt32($info, 3 * 4)
+ )
+
+ # Detect Features
+ $features = @{ }
+ If ($nIds -ge 0x00000001) {
+
+ $info = [CpuID]::Invoke(0x00000001)
+ # convert 16 bytes to 4 ints for compatibility with existing code
+ $info = [Int[]]@(
+ [BitConverter]::ToInt32($info, 0 * 4)
+ [BitConverter]::ToInt32($info, 1 * 4)
+ [BitConverter]::ToInt32($info, 2 * 4)
+ [BitConverter]::ToInt32($info, 3 * 4)
+ )
+
+ $features.MMX = ($info[3] -band ([Int]1 -shl 23)) -ne 0
+ $features.SSE = ($info[3] -band ([Int]1 -shl 25)) -ne 0
+ $features.SSE2 = ($info[3] -band ([Int]1 -shl 26)) -ne 0
+ $features.SSE3 = ($info[2] -band ([Int]1 -shl 00)) -ne 0
+
+ $features.SSSE3 = ($info[2] -band ([Int]1 -shl 09)) -ne 0
+ $features.SSE41 = ($info[2] -band ([Int]1 -shl 19)) -ne 0
+ $features.SSE42 = ($info[2] -band ([Int]1 -shl 20)) -ne 0
+ $features.AES = ($info[2] -band ([Int]1 -shl 25)) -ne 0
+
+ $features.AVX = ($info[2] -band ([Int]1 -shl 28)) -ne 0
+ $features.FMA3 = ($info[2] -band ([Int]1 -shl 12)) -ne 0
+
+ $features.RDRAND = ($info[2] -band ([Int]1 -shl 30)) -ne 0
+ }
+
+ If ($nIds -ge 0x00000007) {
+
+ $info = [CpuID]::Invoke(0x00000007)
+ # convert 16 bytes to 4 ints for compatibility with existing code
+ $info = [Int[]]@(
+ [BitConverter]::ToInt32($info, 0 * 4)
+ [BitConverter]::ToInt32($info, 1 * 4)
+ [BitConverter]::ToInt32($info, 2 * 4)
+ [BitConverter]::ToInt32($info, 3 * 4)
+ )
+
+ $features.AVX2 = ($info[1] -band ([Int]1 -shl 05)) -ne 0
+
+ $features.BMI1 = ($info[1] -band ([Int]1 -shl 03)) -ne 0
+ $features.BMI2 = ($info[1] -band ([Int]1 -shl 08)) -ne 0
+ $features.ADX = ($info[1] -band ([Int]1 -shl 19)) -ne 0
+ $features.MPX = ($info[1] -band ([Int]1 -shl 14)) -ne 0
+ $features.SHA = ($info[1] -band ([Int]1 -shl 29)) -ne 0
+ $features.PREFETCHWT1 = ($info[2] -band ([Int]1 -shl 00)) -ne 0
+
+ $features.AVX512_F = ($info[1] -band ([Int]1 -shl 16)) -ne 0
+ $features.AVX512_CD = ($info[1] -band ([Int]1 -shl 28)) -ne 0
+ $features.AVX512_PF = ($info[1] -band ([Int]1 -shl 26)) -ne 0
+ $features.AVX512_ER = ($info[1] -band ([Int]1 -shl 27)) -ne 0
+ $features.AVX512_VL = ($info[1] -band ([Int]1 -shl 31)) -ne 0
+ $features.AVX512_BW = ($info[1] -band ([Int]1 -shl 30)) -ne 0
+ $features.AVX512_DQ = ($info[1] -band ([Int]1 -shl 17)) -ne 0
+ $features.AVX512_IFMA = ($info[1] -band ([Int]1 -shl 21)) -ne 0
+ $features.AVX512_VBMI = ($info[2] -band ([Int]1 -shl 01)) -ne 0
+ }
+
+ If ($nExIds -ge 0x80000001) {
+
+ $info = [CpuID]::Invoke(0x80000001)
+ # convert 16 bytes to 4 ints for compatibility with existing code
+ $info = [Int[]]@(
+ [BitConverter]::ToInt32($info, 0 * 4)
+ [BitConverter]::ToInt32($info, 1 * 4)
+ [BitConverter]::ToInt32($info, 2 * 4)
+ [BitConverter]::ToInt32($info, 3 * 4)
+ )
+
+ $features.x64 = ($info[3] -band ([Int]1 -shl 29)) -ne 0
+ $features.ABM = ($info[2] -band ([Int]1 -shl 05)) -ne 0
+ $features.SSE4a = ($info[2] -band ([Int]1 -shl 06)) -ne 0
+ $features.FMA4 = ($info[2] -band ([Int]1 -shl 16)) -ne 0
+ $features.XOP = ($info[2] -band ([Int]1 -shl 11)) -ne 0
+ }
+
+ # wrap data into PSObject
+ [PSCustomObject]@{
+ Vendor = $vendor
+ Name = $name
+ Features = $features.Keys.ForEach{ If ($features.$_) { $_ } }
+ }
+}
+
+Function Get-Device {
+
+ Param(
+ [Parameter(Mandatory = $false)]
+ [String[]]$Name = @(),
+ [Parameter(Mandatory = $false)]
+ [String[]]$ExcludeName = @(),
+ [Parameter(Mandatory = $false)]
+ [Switch]$Refresh = $false
+ )
+
+ If ($Name) {
+ $DeviceList = Get-Content ".\Data\Devices.json" | ConvertFrom-Json
+ $Name_Devices = $Name | ForEach-Object {
+ $Name_Split = $_ -split '#'
+ $Name_Split = @($Name_Split | Select-Object -First 1) + @($Name_Split | Select-Object -Skip 1 | ForEach-Object { [Int]$_ })
+ $Name_Split += @("*") * (100 - $Name_Split.Count)
+
+ $Name_Device = $DeviceList.("{0}" -f $Name_Split) | Select-Object *
+ ($Name_Device | Get-Member -MemberType NoteProperty -ErrorAction Ignore).Name | ForEach-Object { $Name_Device.$_ = $Name_Device.$_ -f $Name_Split }
+
+ $Name_Device
+ }
+ }
+
+ If ($ExcludeName) {
+ If (-not $DeviceList) { $DeviceList = Get-Content -Path ".\Data\Devices.json" | ConvertFrom-Json }
+ $ExcludeName_Devices = $ExcludeName | ForEach-Object {
+ $ExcludeName_Split = $_ -split '#'
+ $ExcludeName_Split = @($ExcludeName_Split | Select-Object -First 1) + @($ExcludeName_Split | Select-Object -Skip 1 | ForEach-Object { [Int]$_ })
+ $ExcludeName_Split += @("*") * (100 - $ExcludeName_Split.Count)
+
+ $ExcludeName_Device = $DeviceList.("{0}" -f $ExcludeName_Split) | Select-Object *
+ ($ExcludeName_Device | Get-Member -MemberType NoteProperty -ErrorAction Ignore).Name | ForEach-Object { $ExcludeName_Device.$_ = $ExcludeName_Device.$_ -f $ExcludeName_Split }
+
+ $ExcludeName_Device
+ }
+ }
+
+ If ($Variables.Devices -isnot [Device[]] -or $Refresh) {
+ [Device[]]$Variables.Devices = @()
+
+ $Id = 0
+ $Type_Id = @{ }
+ $Vendor_Id = @{ }
+ $Type_Vendor_Id = @{ }
+
+ $Slot = 0
+ $Type_Slot = @{ }
+ $Vendor_Slot = @{ }
+ $Type_Vendor_Slot = @{ }
+
+ $Index = 0
+ $Type_Index = @{ }
+ $Vendor_Index = @{ }
+ $Type_Vendor_Index = @{ }
+
+ $PlatformId = 0
+ $PlatformId_Index = @{ }
+ $Type_PlatformId_Index = @{ }
+
+ $UnsupportedCPUVendorID = 100
+ $UnsupportedGPUVendorID = 100
+
+ # Get WDDM data
+ Try {
+ Get-CimInstance CIM_Processor | ForEach-Object {
+ $Device_CIM = $_ | ConvertTo-Json -WarningAction SilentlyContinue | ConvertFrom-Json
+
+ # Add normalised values
+ $Variables.Devices += $Device = [PSCustomObject]@{
+ Name = $null
+ Model = $Device_CIM.Name
+ Type = "CPU"
+ Bus = $null
+ Vendor = $(
+ Switch -Regex ($Device_CIM.Manufacturer) {
+ "Advanced Micro Devices" { "AMD" }
+ "Intel" { "INTEL" }
+ "NVIDIA" { "NVIDIA" }
+ "AMD" { "AMD" }
+ Default { $Device_CIM.Manufacturer -replace '\(R\)|\(TM\)|\(C\)|Series|GeForce' -replace '[^A-Z0-9]' -replace '\s+', ' ' }
+ }
+ )
+ Memory = $null
+ MemoryGB = $null
+ }
+
+ $Device | Add-Member @{
+ Id = [Int]$Id
+ Type_Id = [Int]$Type_Id.($Device.Type)
+ Vendor_Id = [Int]$Vendor_Id.($Device.Vendor)
+ Type_Vendor_Id = [Int]$Type_Vendor_Id.($Device.Type).($Device.Vendor)
+ }
+
+ $Device.Name = "$($Device.Type)#$('{0:D2}' -f $Device.Type_Id)"
+ $Device.Model = ((($Device.Model -split ' ' -replace 'Processor', 'CPU' -replace 'Graphics', 'GPU') -notmatch $Device.Type -notmatch $Device.Vendor -notmatch "$([UInt64]($Device.Memory/1GB))GB") + "$([UInt64]($Device.Memory/1GB))GB" -join ' ' -replace '\(R\)|\(TM\)|\(C\)|Series|GeForce' -replace '[^ A-Z0-9\.]' -replace '\s+', ' ').Trim()
+
+ If (-not $Type_Vendor_Id.($Device.Type)) {
+ $Type_Vendor_Id.($Device.Type) = @{ }
+ }
+
+ $Id++
+ $Vendor_Id.($Device.Vendor)++
+ $Type_Vendor_Id.($Device.Type).($Device.Vendor)++
+ If ($Device.Vendor -in $Variables."Supported$($Device.Type)DeviceVendors") { $Type_Id.($Device.Type)++ }
+
+ # Read CPU features
+ $Device | Add-Member CpuFeatures ((Get-CpuId).Features | Sort-Object)
+
+ # Add raw data
+ $Device | Add-Member @{
+ CIM = $Device_CIM
+ }
+ }
+
+ Get-CimInstance CIM_VideoController | ForEach-Object {
+ $Device_CIM = $_ | ConvertTo-Json -WarningAction SilentlyContinue | ConvertFrom-Json
+
+ $Device_PNP = [PSCustomObject]@{ }
+ Get-PnpDevice $Device_CIM.PNPDeviceID | Get-PnpDeviceProperty | ForEach-Object { $Device_PNP | Add-Member $_.KeyName $_.Data }
+ $Device_PNP = $Device_PNP | ConvertTo-Json -WarningAction SilentlyContinue | ConvertFrom-Json
+
+ $Device_Reg = Get-ItemProperty "Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\$($Device_PNP.DEVPKEY_Device_Driver)" -ErrorAction Ignore | ConvertTo-Json -WarningAction SilentlyContinue | ConvertFrom-Json
+
+ # Add normalised values
+ $Variables.Devices += $Device = [PSCustomObject]@{
+ Name = $null
+ Model = $Device_CIM.Name
+ Type = "GPU"
+ Bus = $(
+ If ($Device_PNP.DEVPKEY_Device_BusNumber -is [Int64] -or $Device_PNP.DEVPKEY_Device_BusNumber -is [Int32]) {
+ [Int64]$Device_PNP.DEVPKEY_Device_BusNumber
+ }
+ )
+ Vendor = $(
+ Switch -Regex ([String]$Device_CIM.AdapterCompatibility) {
+ "Advanced Micro Devices" { "AMD" }
+ "Intel" { "INTEL" }
+ "NVIDIA" { "NVIDIA" }
+ "AMD" { "AMD" }
+ Default { $Device_CIM.AdapterCompatibility -replace '\(R\)|\(TM\)|\(C\)|Series|GeForce' -replace '[^A-Z0-9]' -replace '\s+', ' ' }
+ }
+ )
+ Memory = [Math]::Max(([UInt64]$Device_CIM.AdapterRAM), ([uInt64]$Device_Reg.'HardwareInformation.qwMemorySize'))
+ MemoryGB = [Double]([Math]::Round([Math]::Max(([UInt64]$Device_CIM.AdapterRAM), ([uInt64]$Device_Reg.'HardwareInformation.qwMemorySize')) / 0.05GB) / 20) # Round to nearest 50MB
+ }
+
+ $Device | Add-Member @{
+ Id = [Int]$Id
+ Type_Id = [Int]$Type_Id.($Device.Type)
+ Vendor_Id = [Int]$Vendor_Id.($Device.Vendor)
+ Type_Vendor_Id = [Int]$Type_Vendor_Id.($Device.Type).($Device.Vendor)
+ }
+ #Unsupported devices start with DeviceID 100 (to not disrupt device order when running in a Citrix / RDP session)
+ If ($Device.Vendor -in $Variables."Supported$($Device.Type)DeviceVendors") {
+ $Device.Name = "$($Device.Type)#$('{0:D2}' -f $Device.Type_Id)"
+ }
+ ElseIf ($Device.Type -eq "CPU") {
+ $Device.Name = "$($Device.Type)#$('{0:D2}' -f $UnsupportedCPUVendorID++)"
+ }
+ Else {
+ $Device.Name = "$($Device.Type)#$('{0:D2}' -f $UnsupportedGPUVendorID++)"
+ }
+ $Device.Model = ((($Device.Model -split ' ' -replace 'Processor', 'CPU' -replace 'Graphics', 'GPU') -notmatch $Device.Type -notmatch $Device.Vendor -notmatch "$([UInt64]($Device.Memory/1GB))GB") + "$([UInt64]($Device.Memory/1GB))GB" -join ' ' -replace '\(R\)|\(TM\)|\(C\)|Series|GeForce' -replace '[^ A-Z0-9\.]' -replace '\s+', ' ').Trim()
+
+ If (-not $Type_Vendor_Id.($Device.Type)) {
+ $Type_Vendor_Id.($Device.Type) = @{ }
+ }
+
+ $Id++
+ $Vendor_Id.($Device.Vendor)++
+ $Type_Vendor_Id.($Device.Type).($Device.Vendor)++
+ If ($Device.Vendor -in $Variables."Supported$($Device.Type)DeviceVendors") { $Type_Id.($Device.Type)++ }
+
+ # Add raw data
+ $Device | Add-Member @{
+ CIM = $Device_CIM
+ PNP = $Device_PNP
+ Reg = $Device_Reg
+ }
+ }
+ }
+ Catch {
+ Write-Message -Level Warn "WDDM device detection has failed. "
+ }
+
+ # Get OpenCL data
+ Try {
+ [OpenCl.Platform]::GetPlatformIDs() | ForEach-Object {
+ [OpenCl.Device]::GetDeviceIDs($_, [OpenCl.DeviceType]::All) | ForEach-Object { $_ | ConvertTo-Json -WarningAction SilentlyContinue } | Select-Object -Unique | ForEach-Object {
+ $Device_OpenCL = $_ | ConvertFrom-Json
+
+ # Add normalised values
+ $Device = [PSCustomObject]@{
+ Name = $null
+ Model = $Device_OpenCL.Name
+ Type = $(
+ Switch -Regex ([String]$Device_OpenCL.Type) {
+ "CPU" { "CPU" }
+ "GPU" { "GPU" }
+ Default { [String]$Device_OpenCL.Type -replace '\(R\)|\(TM\)|\(C\)|Series|GeForce' -replace '[^A-Z0-9]' -replace '\s+', ' ' }
+ }
+ )
+ Bus = $(
+ If ($Device_OpenCL.PCIBus -is [Int64] -or $Device_OpenCL.PCIBus -is [Int32]) {
+ [Int64]$Device_OpenCL.PCIBus
+ }
+ )
+ Vendor = $(
+ Switch -Regex ([String]$Device_OpenCL.Vendor) {
+ "Advanced Micro Devices" { "AMD" }
+ "Intel" { "INTEL" }
+ "NVIDIA" { "NVIDIA" }
+ "AMD" { "AMD" }
+ Default { [String]$Device_OpenCL.Vendor -replace '\(R\)|\(TM\)|\(C\)|Series|GeForce' -replace '[^A-Z0-9]' -replace '\s+', ' ' }
+ }
+ )
+ Memory = [UInt64]$Device_OpenCL.GlobalMemSize
+ MemoryGB = [Double]([Math]::Round($Device_OpenCL.GlobalMemSize / 0.05GB) / 20) # Round to nearest 50MB
+ }
+
+ $Device | Add-Member @{
+ Id = [Int]$Id
+ Type_Id = [Int]$Type_Id.($Device.Type)
+ Vendor_Id = [Int]$Vendor_Id.($Device.Vendor)
+ Type_Vendor_Id = [Int]$Type_Vendor_Id.($Device.Type).($Device.Vendor)
+ }
+ #Unsupported devices get DeviceID 100 (to not disrupt device order when running in a Citrix / RDP session)
+ If ($Device.Vendor -in $Variables."Supported$($Device.Type)DeviceVendors") {
+ $Device.Name = "$($Device.Type)#$('{0:D2}' -f $Device.Type_Id)"
+ }
+ ElseIf ($Device.Type -eq "CPU") {
+ $Device.Name = "$($Device.Type)#$('{0:D2}' -f $UnsupportedCPUVendorID++)"
+ }
+ Else {
+ $Device.Name = "$($Device.Type)#$('{0:D2}' -f $UnsupportedGPUVendorID++)"
+ }
+ $Device.Model = ((($Device.Model -split ' ' -replace 'Processor', 'CPU' -replace 'Graphics', 'GPU') -notmatch $Device.Type -notmatch $Device.Vendor -notmatch "$([UInt64]($Device.Memory/1GB))GB") + "$([UInt64]($Device.Memory/1GB))GB") -join ' ' -replace '\(R\)|\(TM\)|\(C\)|Series|GeForce' -replace '[^A-Z0-9 ]' -replace '\s+', ' '
+
+ If (-not $Type_Vendor_Id.($Device.Type)) {
+ $Type_Vendor_Id.($Device.Type) = @{ }
+ }
+
+ If ($Variables.Devices | Where-Object Type -EQ $Device.Type | Where-Object Bus -EQ $Device.Bus) {
+ $Device = $Variables.Devices | Where-Object Type -EQ $Device.Type | Where-Object Bus -EQ $Device.Bus
+ }
+ ElseIf ($Device.Type -eq "GPU" -and ($Device.Vendor -eq "AMD" -or $Device.Vendor -eq "NVIDIA")) {
+ $Variables.Devices += $Device
+
+ If (-not $Type_Vendor_Index.($Device.Type)) {
+ $Type_Vendor_Index.($Device.Type) = @{ }
+ }
+
+ $Id++
+ $Vendor_Id.($Device.Vendor)++
+ $Type_Vendor_Id.($Device.Type).($Device.Vendor)++
+ $Type_Id.($Device.Type)++
+ }
+
+ # Add OpenCL specific data
+ $Device | Add-Member @{
+ Index = [Int]$Index
+ Type_Index = [Int]$Type_Index.($Device.Type)
+ Vendor_Index = [Int]$Vendor_Index.($Device.Vendor)
+ Type_Vendor_Index = [Int]$Type_Vendor_Index.($Device.Type).($Device.Vendor)
+ PlatformId = [Int]$PlatformId
+ PlatformId_Index = [Int]$PlatformId_Index.($PlatformId)
+ Type_PlatformId_Index = [Int]$Type_PlatformId_Index.($Device.Type).($PlatformId)
+ } -Force
+
+ # Add raw data
+ $Device | Add-Member @{
+ OpenCL = $Device_OpenCL
+ } -Force
+
+
+ If (-not $Type_Vendor_Index.($Device.Type)) {
+ $Type_Vendor_Index.($Device.Type) = @{ }
+ }
+ If (-not $Type_PlatformId_Index.($Device.Type)) {
+ $Type_PlatformId_Index.($Device.Type) = @{ }
+ }
+
+ $Index++
+ $Type_Index.($Device.Type)++
+ $Vendor_Index.($Device.Vendor)++
+ $Type_Vendor_Index.($Device.Type).($Device.Vendor)++
+ $PlatformId_Index.($PlatformId)++
+ $Type_PlatformId_Index.($Device.Type).($PlatformId)++
+ }
+
+ $PlatformId++
+ }
+
+ $Variables.Devices | Where-Object Vendor -ne "CitrixSystemsInc" | Where-Object Bus -Is [Int64] | Sort-Object Bus | ForEach-Object {
+ $_ | Add-Member @{
+ Slot = [Int]$Slot
+ Type_Slot = [Int]$Type_Slot.($_.Type)
+ Vendor_Slot = [Int]$Vendor_Slot.($_.Vendor)
+ Type_Vendor_Slot = [Int]$Type_Vendor_Slot.($_.Type).($_.Vendor)
+ }
+
+ If (-not $Type_Vendor_Slot.($_.Type)) {
+ $Type_Vendor_Slot.($_.Type) = @{ }
+ }
+
+ $Slot++
+ $Type_Slot.($_.Type)++
+ $Vendor_Slot.($_.Vendor)++
+ $Type_Vendor_Slot.($_.Type).($_.Vendor)++
+ }
+ }
+ Catch {
+ Write-Message -Level Warn "OpenCL device detection has failed. "
+ }
+ }
+
+ $Variables.Devices | ForEach-Object {
+ [Device]$Device = $_
+
+ $Device.Bus_Index = @($Variables.Devices.Bus | Sort-Object).IndexOf([Int]$Device.Bus)
+ $Device.Bus_Type_Index = @(($Variables.Devices | Where-Object Type -EQ $Device.Type).Bus | Sort-Object).IndexOf([Int]$Device.Bus)
+ $Device.Bus_Vendor_Index = @(($Variables.Devices | Where-Object Vendor -EQ $Device.Vendor).Bus | Sort-Object).IndexOf([Int]$Device.Bus)
+ $Device.Bus_Platform_Index = @(($Variables.Devices | Where-Object Platform -EQ $Device.Platform).Bus | Sort-Object).IndexOf([Int]$Device.Bus)
+
+ If (-not $Name -or ($Name_Devices | Where-Object { ($Device | Select-Object (($_ | Get-Member -MemberType NoteProperty -ErrorAction Ignore).Name)) -like ($_ | Select-Object (($_ | Get-Member -MemberType NoteProperty -ErrorAction Ignore).Name)) })) {
+ If (-not $ExcludeName -or -not ($ExcludeName_Devices | Where-Object { ($Device | Select-Object (($_ | Get-Member -MemberType NoteProperty -ErrorAction Ignore).Name)) -like ($_ | Select-Object (($_ | Get-Member -MemberType NoteProperty -ErrorAction Ignore).Name)) })) {
+ $Device
+ }
+ }
+ }
+}
+
+Filter ConvertTo-Hash {
+
+ $Units = " kMGTPEZY " # k(ilo) in small letters, see https://en.wikipedia.org/wiki/Metric_prefix
+ $Base1000 = [Math]::Truncate([Math]::Log([Math]::Abs([Double]$_), [Math]::Pow(1000, 1)))
+ $Base1000 = [Math]::Max([Double]0, [Math]::Min($Base1000, $Units.Length - 1))
+ "{0:n2} $($Units[$Base1000])H" -f ($_ / [Math]::Pow(1000, $Base1000))
+}
+
+Function Get-DigitsFromValue {
+
+ # To get same numbering scheme regardless of value base currency value (size) to determine formatting
+
+ # Length is calculated as follows:
+ # Output will have as many digits as the integer value is to the power of 10
+ # e.g. Rate is between 100 -and 999, then Digits is 3
+ # The bigger the number, the more decimal digits
+ # Use $Offset to add/remove decimal places
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [Double]$Value,
+ [Parameter(Mandatory = $false)]
+ [Int]$Offset = 0
+ )
+
+ $Digits = [math]::Floor($Value).ToString().Length + $Offset
+ If ($Digits -lt 0) { $Digits = 0 }
+ If ($Digits -gt 10) { $Digits = 10 }
+
+ $Digits
+}
+
+Function ConvertTo-LocalCurrency {
+
+ # To get same numbering scheme regardless of value
+ # Use $Offset to add/remove decimal places
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [Double]$Value,
+ [Parameter(Mandatory = $true)]
+ [Double]$Rate,
+ [Parameter(Mandatory = $false)]
+ [Int]$Offset
+ )
+
+ $Digits = ([math]::truncate(10 - $Offset - [math]::log($Rate, 10)))
+ If ($Digits -lt 0) { $Digits = 0 }
+ If ($Digits -gt 10) { $Digits = 10 }
+
+ ($Value * $Rate).ToString("N$($Digits)")
+}
+
+Function Get-Combination {
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [Array]$Value,
+ [Parameter(Mandatory = $false)]
+ [Int]$SizeMax = $Value.Count,
+ [Parameter(Mandatory = $false)]
+ [Int]$SizeMin = 1
+ )
+
+ $Combination = [PSCustomObject]@{ }
+
+ For ($i = 0; $i -lt $Value.Count; $i++) {
+ $Combination | Add-Member @{ [Math]::Pow(2, $i) = $Value[$i] }
+ }
+
+ $Combination_Keys = ($Combination | Get-Member -MemberType NoteProperty).Name
+
+ For ($i = $SizeMin; $i -le $SizeMax; $i++) {
+ $x = [Math]::Pow(2, $i) - 1
+
+ While ($x -le [Math]::Pow(2, $Value.Count) - 1) {
+ [PSCustomObject]@{ Combination = $Combination_Keys | Where-Object { $_ -band $x } | ForEach-Object { $Combination.$_ } }
+ $smallest = ($x -band - $x)
+ $ripple = $x + $smallest
+ $new_smallest = ($ripple -band - $ripple)
+ $ones = (($new_smallest / $smallest) -shr 1) - 1
+ $x = $ripple -bor $ones
+ }
+ }
+}
+
+Function Invoke-CreateProcess {
+
+ # Based on https://github.com/FuzzySecurity/PowerShell-Suite/blob/master/Invoke-CreateProcess.ps1
+
+ Param (
+ [Parameter(Mandatory = $true)]
+ [String]$BinaryPath,
+ [Parameter(Mandatory = $false)]
+ [String]$ArgumentList = $null,
+ [Parameter(Mandatory = $false)]
+ [String]$WorkingDirectory = "",
+ [Parameter(Mandatory = $false)]
+ [ValidateRange(-2, 3)]
+ [Int]$Priority = 0, # NORMAL
+ [Parameter(Mandatory = $false)]
+ [String[]]$EnvBlock = "",
+ [Parameter(Mandatory = $false)]
+ [String]$CreationFlags = 0x00000010, # CREATE_NEW_CONSOLE
+ [Parameter(Mandatory = $false)]
+ [String]$MinerWindowStyle = "minimized",
+ [Parameter(Mandatory = $false)]
+ [String]$StartF = 0x00000001, # STARTF_USESHOWWINDOW
+ [Parameter(Mandatory = $false)]
+ [String]$JobName,
+ [Parameter(Mandatory = $false)]
+ [String]$LogFile
+ )
+
+ $Job = Start-ThreadJob -Name $JobName -ThrottleLimit 99 -ArgumentList $BinaryPath, $ArgumentList, $WorkingDirectory, $EnvBlock, $CreationFlags, $MinerWindowStyle, $StartF, $PID {
+ Param($BinaryPath, $ArgumentList, $WorkingDirectory, $EnvBlock, $CreationFlags, $MinerWindowStyle, $StartF, $ControllerProcessID)
+
+ $ControllerProcess = Get-Process -Id $ControllerProcessID
+ If ($null -eq $ControllerProcess) { Return }
+
+ # Define all the structures for CreateProcess
+ Add-Type -TypeDefinition @"
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+[StructLayout(LayoutKind.Sequential)]
+public struct PROCESS_INFORMATION
+{
+ public IntPtr hProcess; public IntPtr hThread; public uint dwProcessId; public uint dwThreadId;
+}
+
+[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+public struct STARTUPINFO
+{
+ public uint cb; public string lpReserved; public string lpDesktop; public string lpTitle;
+ public uint dwX; public uint dwY; public uint dwXSize; public uint dwYSize; public uint dwXCountChars;
+ public uint dwYCountChars; public uint dwFillAttribute; public uint dwFlags; public short wShowWindow;
+ public short cbReserved2; public IntPtr lpReserved2; public IntPtr hStdInput; public IntPtr hStdOutput;
+ public IntPtr hStdError;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct SECURITY_ATTRIBUTES
+{
+ public int length; public IntPtr lpSecurityDescriptor; public bool bInheritHandle;
+}
+
+public static class Kernel32
+{
+ [DllImport("kernel32.dll", SetLastError=true)]
+ public static extern bool CreateProcess(
+ string lpApplicationName, string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
+ ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags,
+ IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo,
+ out PROCESS_INFORMATION lpProcessInformation);
+}
+"@
+
+ $ShowWindow = $(
+ Switch ($MinerWindowStyle) {
+ "hidden" { "0x0000" } # SW_HIDE
+ "normal" { "0x0001" } # SW_SHOWNORMAL
+ Default { "0x0007" } # SW_SHOWMINNOACTIVE
+ }
+ )
+ # Set local environment
+ $EnvBlock | Select-Object | ForEach-Object { Set-Item -Path "Env:$($_ -split '=' | Select-Object -First 1)" "$($_ -split '=' | Select-Object -Index 1)" -Force }
+
+ # StartupInfo Struct
+ $StartupInfo = New-Object STARTUPINFO
+ $StartupInfo.dwFlags = $StartF # StartupInfo.dwFlag
+ $StartupInfo.wShowWindow = $ShowWindow # StartupInfo.ShowWindow
+ $StartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($StartupInfo) # Struct Size
+
+ # ProcessInfo Struct
+ $ProcessInfo = New-Object PROCESS_INFORMATION
+
+ # SECURITY_ATTRIBUTES Struct (Process & Thread)
+ $SecAttr = New-Object SECURITY_ATTRIBUTES
+ $SecAttr.Length = [System.Runtime.InteropServices.Marshal]::SizeOf($SecAttr)
+
+ # CreateProcess --> lpCurrentDirectory
+ If (-not $WorkingDirectory) { $WorkingDirectory = [IntPtr]::Zero }
+
+ # Call CreateProcess
+ [Kernel32]::CreateProcess($BinaryPath, "$BinaryPath $ArgumentList", [ref]$SecAttr, [ref]$SecAttr, $false, $CreationFlags, [IntPtr]::Zero, $WorkingDirectory, [ref]$StartupInfo, [ref]$ProcessInfo) | Out-Null
+
+ $Process = Get-Process -Id $ProcessInfo.dwProcessId
+ If ($null -eq $Process) {
+ [PSCustomObject]@{ ProcessId = $null }
+ Return
+ }
+
+ [PSCustomObject]@{ProcessId = $Process.Id; ProcessHandle = $Process.Handle }
+
+ Do { If ($ControllerProcess.WaitForExit(1000)) { $Process.CloseMainWindow() | Out-Null } }
+ While ($Process.HasExited -eq $false)
+ }
+
+ Return $Job
+}
+
+Function Start-SubProcess {
+
+ [CmdletBinding()]
+ Param(
+ [Parameter(Mandatory = $true)]
+ [String]$FilePath,
+ [Parameter(Mandatory = $false)]
+ [String]$ArgumentList = "",
+ [Parameter(Mandatory = $false)]
+ [String]$LogPath = "",
+ [Parameter(Mandatory = $false)]
+ [String]$WorkingDirectory = "",
+ [ValidateRange(-2, 3)]
+ [Parameter(Mandatory = $false)]
+ [Int]$Priority = 0,
+ [Parameter(Mandatory = $false)]
+ [String[]]$EnvBlock
+ )
+
+ If ($EnvBlock) { $EnvBlock | ForEach-Object { Set-Item -Path "Env:$($_ -split '=' | Select-Object -First 1)" "$($_ -split '=' | Select-Object -Index 1)" -Force } }
+
+ $ScriptBlock = "Set-Location '$WorkingDirectory'; (Get-Process -Id `$PID).PriorityClass = '$(@{-2 = "Idle"; -1 = "BelowNormal"; 0 = "Normal"; 1 = "AboveNormal"; 2 = "High"; 3 = "RealTime"}[$Priority])'; "
+ $ScriptBlock += "& '$FilePath'"
+ If ($ArgumentList) { $ScriptBlock += " $ArgumentList" }
+ $ScriptBlock += " *>&1"
+ $ScriptBlock += " | Write-Output"
+ If ($LogPath) { $ScriptBlock += " | Tee-Object '$LogPath'" }
+
+ Start-ThreadJob -ThrottleLimit 99 ([ScriptBlock]::Create($ScriptBlock))
+}
+
+Function Expand-WebRequest {
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [String]$Uri,
+ [Parameter(Mandatory = $false)]
+ [String]$Path = ""
+ )
+
+ # Set current path used by .net methods to the same as the script's path
+ [Environment]::CurrentDirectory = $ExecutionContext.SessionState.Path.CurrentFileSystemLocation
+
+ If (-not $Path) { $Path = Join-Path ".\Downloads" ([IO.FileInfo](Split-Path $Uri -Leaf)).BaseName }
+ If (-not (Test-Path -Path ".\Downloads" -PathType Container)) { New-Item "Downloads" -ItemType "directory" | Out-Null }
+ $FileName = Join-Path ".\Downloads" (Split-Path $Uri -Leaf)
+
+ If (Test-Path $FileName -PathType Leaf) { Remove-Item $FileName }
+ [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+ Invoke-WebRequest -Uri $Uri -OutFile $FileName -TimeoutSec 5 -UseBasicParsing
+
+ If (".msi", ".exe" -contains ([IO.FileInfo](Split-Path $Uri -Leaf)).Extension) {
+ Start-Process $FileName "-qb" -Wait
+ }
+ Else {
+ $Path_Old = (Join-Path (Split-Path (Split-Path $Path)) ([IO.FileInfo](Split-Path $Uri -Leaf)).BaseName)
+ $Path_New = Split-Path $Path
+
+ If (Test-Path $Path_Old -PathType Container) { Remove-Item $Path_Old -Recurse -Force }
+ Start-Process ".\Utils\7z" "x `"$([IO.Path]::GetFullPath($FileName))`" -o`"$([IO.Path]::GetFullPath($Path_Old))`" -y -spe" -Wait -WindowStyle Hidden
+
+ If (Test-Path $Path_New -PathType Container) { Remove-Item $Path_New -Recurse -Force }
+
+ # use first (topmost) directory, some miners, e.g. ClaymoreDual_v11.9, contain multiple miner binaries for different driver versions in various sub dirs
+ $Path_Old = (Get-ChildItem -Path $Path_Old -File -Recurse | Where-Object { $_.Name -EQ $(Split-Path $Path -Leaf) }).Directory | Select-Object -First 1
+
+ If ($Path_Old) {
+ Move-Item $Path_Old $Path_New -PassThru | ForEach-Object -Process { $_.LastWriteTime = Get-Date }
+ $Path_Old = (Join-Path (Split-Path (Split-Path $Path)) ([IO.FileInfo](Split-Path $Uri -Leaf)).BaseName)
+ If (Test-Path $Path_Old -PathType Container) { Remove-Item -Path $Path_Old -Recurse -Force }
+ }
+ Else {
+ Throw "Error: Cannot find '$Path'."
+ }
+ }
+}
+
+Function Get-Algorithm {
+
+ Param(
+ [Parameter(Mandatory = $false)]
+ [String]$Algorithm
+ )
+
+ If (-not (Test-Path Variable:Global:Algorithms -ErrorAction SilentlyContinue)) {
+ $Global:Algorithms = Get-Content ".\Data\Algorithms.json" | ConvertFrom-Json
+ }
+
+ $Algorithm = (Get-Culture).TextInfo.ToTitleCase($Algorithm.ToLower() -replace '-|_|/| ')
+
+ If ($Global:Algorithms.$Algorithm) { $Global:Algorithms.$Algorithm }
+ Else { $Algorithm }
+}
+
+Function Get-Region {
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [String]$Region,
+ [Parameter(Mandatory = $false)]
+ [Switch]$List = $false
+ )
+
+ If (-not (Test-Path Variable:Global:Regions -ErrorAction SilentlyContinue)) {
+ $Global:Regions = Get-Content -Path ".\Data\Regions.json" -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop
+ }
+
+ If ($List) { $Global:Regions.$Region }
+ ElseIf ($Global:Regions.$Region) { $($Global:Regions.$Region | Select-Object -First 1) }
+ Else { $Region }
+}
+
+Function Add-CoinName {
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [String]$Currency,
+ [Parameter(Mandatory = $true)]
+ [String]$CoinName
+ )
+
+ # Get mutex. Mutexes are shared across all threads and processes.
+ # This lets us ensure only one thread is trying to write to the file at a time.
+ $Mutex = New-Object System.Threading.Mutex($false, "$($PWD -replace '[^A-Z0-9]')DataCoinnames.json")
+
+ # Attempt to aquire mutex, waiting up to 1 second if necessary. If aquired, update the coin names file and release mutex. Otherwise, display an error.
+ If ($Mutex.WaitOne(1000)) {
+
+ $Global:CoinNames = Get-Content -Path ".\Data\CoinNames.json" -ErrorAction Ignore | ConvertFrom-Json -ErrorAction Ignore
+ $Global:CoinNames | Add-Member $Currency ((Get-Culture).TextInfo.ToTitleCase($CoinName.Trim().ToLower()) -replace '[^A-Z0-9\$\.]' -replace 'coin$', 'Coin' -replace 'bitcoin$', 'Bitcoin') -Force
+ $Global:CoinNames | Get-SortedObject | ConvertTo-Json | Out-File -Path ".\Data\CoinNames.json" -ErrorAction SilentlyContinue -Encoding utf8NoBOM -Force
+ [void]$Mutex.ReleaseMutex()
+ }
+}
+
+Function Get-CoinName {
+
+ Param(
+ [Parameter(Mandatory = $false)]
+ [String]$Currency
+ )
+
+ If (-not (Test-Path Variable:Global:CoinNames -ErrorAction SilentlyContinue)) {
+ $Global:CoinNames = Get-Content -Path ".\Data\CoinNames.json" -ErrorAction Ignore | ConvertFrom-Json -ErrorAction Ignore
+ }
+
+ If ($Global:CoinNames.$Currency) {
+ Return $Global:CoinNames.$Currency
+ }
+ If ($Currency) {
+ $Global:CoinNames = Get-Content -Path ".\Data\CoinNames.json" -ErrorAction Ignore | ConvertFrom-Json -ErrorAction Ignore
+ If ($Global:CoinNames.$Currency) {
+ Return $Global:CoinNames.$Currency
+ }
+ }
+ Return $null
+}
+
+Function Get-PoolBaseName {
+
+ Param(
+ [Parameter(Mandatory = $false)]
+ [String[]]$PoolNames
+ )
+
+ $PoolNames -replace "24hr$|Coins$|Coins24hr$|CoinsPlus$|Plus$"
+}
+
+Function Get-NMVersion {
+
+ # Check if new version is available
+ Try {
+ $UpdateVersion = (Invoke-WebRequest -Uri "https://raw.githubusercontent.com/Minerx117/NemosMiner/master/Version.txt" -TimeoutSec 15 -UseBasicParsing -SkipCertificateCheck -Headers @{ "Cache-Control" = "no-cache" }).Content | ConvertFrom-Json
+
+ If ($UpdateVersion.Product -eq $Variables.Branding.ProductLabel -and [Version]$UpdateVersion.Version -gt $Variables.Branding.Version) {
+ If ($UpdateVersion.AutoUpdate -eq $true) {
+ If ($Config.AutoUpdate) {
+ Initialize-Autoupdate -UpdateVersion $UpdateVersion
+ }
+ Else {
+ Write-Message -Level Verbose "Version checker: New Version $($UpdateVersion.Version) found. Auto Update is disabled in config - You must update manually."
+ }
+ }
+ Else {
+ Write-Message -Level Verbose "Version checker: New Version is available. $($UpdateVersion.Version) does not support auto-update. You must update manually."
+ }
+ }
+ Else {
+ Write-Message -Level Verbose "Version checker: $($Variables.Branding.ProductLabel) $($Variables.Branding.Version) is current - no update available."
+ }
+ }
+ Catch {
+ Write-Message -Level Warn "Version checker could not contact update server. $($Variables.Branding.ProductLabel) will automatically retry with 24hrs."
+ }
+}
+
+Function Initialize-Autoupdate {
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [PSCustomObject]$UpdateVersion
+ )
+
+ Set-Location $Variables.MainPath
+ $UpdateLog = "$($Variables.MainPath)\Logs\AutoupdateLog_$(Get-Date -Format "yyyy-MM-dd_HH-mm-ss").txt"
+ $BackupFile = "AutoupdateBackup_$(Get-Date -Format "yyyy-MM-dd_HH-mm-ss").zip"
+
+ # GitHub only suppors TLSv1.2 since feb 22 2018
+ [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"
+
+ $NemosMinerFileHash = (Get-FileHash ".\$($Variables.Branding.ProductLabel).ps1").Hash
+
+ "Version checker: New version $($UpdateVersion.Version) found. " | Tee-Object $UpdateLog | Write-Message -Level Verbose
+ "Starting auto update - Logging changes to '.\$($UpdateLog.Replace("$(Convert-Path '.\')\", ''))'." | Tee-Object $UpdateLog | Write-Message -Level Verbose
+
+ # Setting autostart to true
+ If ($Variables.MiningStatus -eq [MinerStatus]::Running) { $Config.AutoStart = $true }
+
+ # Download update file
+ $UpdateFileName = ".\$($UpdateVersion.Product)-$($UpdateVersion.Version)"
+ "Downloading new version..." | Tee-Object $UpdateLog -Append | Write-Message -Level Verbose
+ Try {
+ Invoke-WebRequest -Uri $UpdateVersion.Uri -OutFile "$($UpdateFileName).zip" -TimeoutSec 15 -UseBasicParsing
+ }
+ Catch {
+ "Downloading failed. Cannot complete auto-update :-(" | Tee-Object $UpdateLog -Append | Write-Message -Level Error
+ Return
+ }
+ If (-not (Test-Path -Path ".\$($UpdateFileName).zip" -PathType Leaf)) {
+ Write-Message -Level Error "Cannot find update file. Cannot complete auto-update :-("
+ Return
+ }
+
+ If ($Variables.Branding.Version -le [System.Version]"3.9.9.17" -and $UpdateVersion.Version -ge [System.Version]"3.9.9.17") {
+ # Balances & earnings files are no longer compatible
+ Write-Message -Level Warn "Balances & Earnings files are no longer compatible and will be reset."
+ }
+
+ # Stop processes
+ $Variables.NewMiningStatus = "Idle"
+
+ # Backup current version folder in zip file; exclude existing zip files and download folder
+ "Backing up current version as '.\$($BackupFile)'..." | Tee-Object $UpdateLog -Append | Write-Message -Level Verbose
+ Start-Process ".\Utils\7z" "a $($BackupFile) .\* -x!*.zip -x!downloads -x!logs -x!cache -x!$UpdateLog -bb1 -bd" -RedirectStandardOutput "$($UpdateLog)_tmp" -Wait -WindowStyle Hidden
+ Add-Content $UpdateLog (Get-Content -Path "$($UpdateLog)_tmp")
+ Remove-Item -Path "$($UpdateLog)_tmp" -Force
+
+ If (-not (Test-Path .\$BackupFile -PathType Leaf)) {
+ "Backup failed. Cannot complete auto-update :-(" | Tee-Object $UpdateLog -Append | Write-Message -Level Error
+ Return
+ }
+
+ #Stop all background processes
+ Stop-Mining
+ Stop-BrainJob
+ Stop-IdleDetection
+ Stop-BalancesTracker
+
+ If ($Variables.Branding.Version -le [System.Version]"3.9.9.17" -and $UpdateVersion -ge [System.Version]"3.9.9.17") {
+ # Remove balances & earnings files that are no longer compatible
+ If (Test-Path -Path ".\Logs\BalancesTrackerData*.*") { Get-ChildItem -Path ".\Logs\BalancesTrackerData*.*" -File | ForEach-Object { Remove-Item -Recurse -Path $_.FullName -Force; "Removed '$_'" | Out-File -FilePath $UpdateLog -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue} }
+ If (Test-Path -Path ".\Logs\DailyEarnings*.*") { Get-ChildItem -Path ".\Logs\DailyEarnings*.*" -File | ForEach-Object { Remove-Item -Recurse -Path $_.FullName -Force; "Removed '$_'" | Out-File -FilePath $UpdateLog -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue } }
+ }
+
+ # Move data files from '\Logs' to '\Data'
+ If (Test-Path -Path ".\Logs\BalancesTrackerData*.json" -PathType Leaf) { Move-Item ".\Logs\BalancesTrackerData*.json" ".\Data" -Force }
+ If (Test-Path -Path ".\Logs\EarningsChartData.json" -PathType Leaf) { Move-Item ".\Logs\EarningsChartData.json" ".\Data" -Force }
+ If (Test-Path -Path ".\Logs\DailyEarnings*.csv" -PathType Leaf) { Move-Item ".\Logs\DailyEarnings*.csv" ".\Data" -Force }
+ If (Test-Path -Path ".\Logs\PoolsLastUsed.json" -PathType Leaf) { Move-Item ".\Logs\PoolsLastUsed.json" ".\Data" -Force }
+
+ # Pre update specific actions if any
+ # Use PreUpdateActions.ps1 in new release to place code
+ # If (Test-Path -Path ".\$UpdateFilePath\PreUpdateActions.ps1" -PathType Leaf) {
+ # Invoke-Expression (Get-Content ".\$UpdateFilePath\PreUpdateActions.ps1" -Raw)
+ # }
+
+ # Empty folders
+ If (Test-Path -Path ".\Balances") { Get-ChildItem -Path ".\Balances" -File | ForEach-Object { Remove-Item -Recurse -Path $_.FullName -Force; "Removed '$_'" | Out-File -FilePath $UpdateLog -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue } }
+ If (Test-Path -Path ".\Brains") { Get-ChildItem -Path ".\Brains" -File | ForEach-Object { Remove-Item -Recurse -Path $_.FullName -Force; "Removed '$_'" | Out-File -FilePath $UpdateLog -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue } }
+ If (Test-Path -Path ".\Pools") { Get-ChildItem -Path ".\Pools\" -File | ForEach-Object { Remove-Item -Recurse -Path $_.FullName -Force; "Removed '$_'" | Out-File -FilePath $UpdateLog -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue } }
+ If (Test-Path -Path ".\Web") { Get-ChildItem -Path ".\Web" -File | ForEach-Object { Remove-Item -Recurse -Path $_.FullName -Force; "Removed '$_'" | Out-File -FilePath $UpdateLog -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue } }
+
+ # Unzip in child folder excluding config
+ "Unzipping update..." | Tee-Object $UpdateLog -Append | Write-Message -Level Verbose
+ Start-Process ".\Utils\7z" "x $($UpdateFileName).zip -o.\$($UpdateFileName) -y -spe -xr!config -bb1 -bd" -RedirectStandardOutput "$($UpdateLog)_tmp" -Wait -WindowStyle Hidden
+ Add-Content $UpdateLog (Get-Content -Path "$($UpdateLog)_tmp")
+ Remove-Item -Path "$($UpdateLog)_tmp" -Force
+
+ #Update files are in a subdirectory
+ $UpdateFilePath = $UpdateFileName
+ If ((Get-ChildItem -Path $UpdateFileName -Directory).Count -eq 1) {
+ $UpdateFilePath = "$UpdateFileName\$((Get-ChildItem -Path $UpdateFileName -Directory).Name)"
+ }
+
+ # Stop Snaketail
+ If (Get-CimInstance CIM_Process | Where-Object ExecutablePath -EQ $Variables.SnakeTailExe) {
+ "Stopping SnakeTail..." | Tee-Object $UpdateLog -Append | Write-Message -Level Verbose
+ (Get-CimInstance CIM_Process | Where-Object ExecutablePath -EQ $Variables.SnakeTailExe).ProcessId | ForEach-Object { Stop-Process -Id $_ }
+ }
+
+ # Copy files
+ "Copying new files..." | Tee-Object $UpdateLog -Append | Write-Message -Level Verbose
+ Get-ChildItem -Path ".\$UpdateFilePath\*" -Recurse | ForEach-Object {
+ $DestPath = $_.FullName.Replace($UpdateFilePath -replace "^\.", "")
+ If ($_.Attributes -eq "Directory") {
+ If (-not (Test-Path -Path $DestPath -PathType Container)) {
+ New-Item -Path $DestPath -ItemType Directory -Force
+ "Created directory '$DestPath'."
+ }
+ }
+ Else {
+ Copy-Item -Path $_ -Destination $DestPath -Force -ErrorAction Ignore
+ "Copied '$($_.Name)' to '$Destpath'." | Out-File -FilePath $UpdateLog -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+ }
+ }
+
+ # Remove OrphanedMinerStats; must be done after new miner files habe veen unpacked
+ Remove-OrphanedMinerStats | Out-Null
+
+ # Start Log reader (SnakeTail) [https://github.com/snakefoot/snaketail-net]
+ Start-LogReader
+
+ # Post update actions
+ If (Test-Path -Path ".\OptionalMiners" -PathType Container) {
+ # Remove any obsolete Optional miner file (ie. not in new version OptionalMiners)
+ Get-ChildItem -Path ".\OptionalMiners" -File | Where-Object { $_.name -notin (Get-ChildItem -Path ".\$UpdateFilePath\OptionalMiners" -File).name } | ForEach-Object { Remove-Item -Path $_.FullName -Recurse -Force; "Removed '$_'" | Out-File -FilePath $UpdateLog -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue }
+ # Update Optional Miners to Miners If in use
+ Get-ChildItem -Path ".\OptionalMiners" -File | Where-Object { $_.name -in (Get-ChildItem -Path ".\Miners" -File).name } | ForEach-Object { Copy-Item -Path $_.FullName -Destination ".\Miners" -Force; "Copied $($_.Name) to '.\Miners'" | Out-File -FilePath $UpdateLog -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue }
+ }
+
+ # Remove any obsolete miner file (ie. not in new version Miners or OptionalMiners)
+ If (Test-Path -Path ".\Miners" -PathType Container) { Get-ChildItem -Path ".\Miners" -File | Where-Object { $_.name -notin (Get-ChildItem -Path ".\$UpdateFilePath\Miners" -File).name -and $_.name -notin (Get-ChildItem -Path ".\$UpdateFilePath\OptionalMiners" -File).name } | ForEach-Object { Remove-Item -Path $_.FullName -Recurse -Force; "Removed '$_'" | Out-File -FilePath $UpdateLog -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue } }
+
+ # Get all miner names and remove obsolete stat files from miners that no longer exist
+ $MinerNames = @( )
+ If (Test-Path -Path ".\Miners" -PathType Container) { Get-ChildItem -Path ".\Miners" -File | ForEach-Object { $MinerNames += $_.Name -replace $_.Extension } }
+ If (Test-Path -Path ".\OptionalMiners" -PathType Container) { Get-ChildItem -Path ".\OptionalMiners" -File | ForEach-Object { $MinerNames += $_.Name -replace $_.Extension } }
+ If (Test-Path -Path ".\Stats" -PathType Container) {
+ Get-ChildItem -Path ".\Stats\*_Hashrate.txt" -File | Where-Object { (($_.name -Split '-' | Select-Object -First 2) -Join '-') -notin $MinerNames } | ForEach-Object { Remove-Item -Path $_ -Force; "Removed '$_'" | Out-File -FilePath $UpdateLog -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue }
+ Get-ChildItem -Path ".\Stats\*_PowerUsage.txt" -File | Where-Object { (($_.name -Split '-' | Select-Object -First 2) -Join '-') -notin $MinerNames } | ForEach-Object { Remove-Item -Path $_ -Force; "Removed '$_'" | Out-File -FilePath $UpdateLog -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue }
+ }
+
+ If ($ObsoleteStatFiles.Count -gt 0) {
+ "Removing obsolete stat files from miners that no longer exist..." | Tee-Object $UpdateLog -Append | Write-Message -Level Verbose
+ $ObsoleteStatFiles | ForEach-Object {
+ Remove-Item -Path $_ -Force
+ "Removed '$_'." | Out-File -FilePath $UpdateLog -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+ }
+ }
+
+ # Remove temp files
+ "Removing temporary files..." | Tee-Object -FilePath $UpdateLog -Append | Write-Message -Level Verbose
+ Remove-Item .\$UpdateFileName -Force -Recurse
+ Remove-Item ".\$($UpdateFileName).zip" -Force
+ If (Test-Path -Path ".\PreUpdateActions.ps1" -PathType Leaf) {
+ Remove-Item ".\PreUpdateActions.ps1" -Force
+ "Removed '.\PreUpdateActions.ps1'."
+ }
+ If (Test-Path -Path ".\PostUpdateActions.ps1" -PathType Leaf) {
+ Remove-Item ".\PostUpdateActions.ps1" -Force
+ "Removed '.\PostUpdateActions.ps1'."
+ }
+ Get-ChildItem -Path "AutoupdateBackup_*.zip" -File | Where-Object { $_.name -ne $BackupFile } | Sort-Object LastWriteTime -Descending | Select-Object -SkipLast 2 | ForEach-Object { Remove-Item -Path $_ -Force -Recurse; "Removed '$_'." | Out-File -FilePath $UpdateLog -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue }
+ Get-ChildItem -Path ".\Logs\AutoupdateBackup_*.zip" -File | Where-Object { $_.name -ne $UpdateLog } | Sort-Object LastWriteTime -Descending | Select-Object -SkipLast 2 | ForEach-Object { Remove-Item -Path $_ -Force -Recurse; "Removed '$_'." | Out-File -FilePath $UpdateLog -Append -Encoding utf8NoBOM -ErrorAction SilentlyContinue }
+
+ # Start new instance
+ If ($UpdateVersion.RequireRestart -or $NemosMinerFileHash -ne (Get-FileHash ".\$($Variables.Branding.ProductLabel).ps1").Hash) {
+ "Starting updated version..." | Tee-Object $UpdateLog -Append | Write-Message -Level Verbose
+ $StartCommand = (Get-Process -Id $PID).CommandLine
+ $NewKid = Invoke-CimMethod -ClassName Win32_Process -MethodName "Create" -Arguments @{ CommandLine = "$StartCommand"; CurrentDirectory = $Variables.MainPath }
+ Start-Sleep 5
+
+ # Giving 10 seconds for process to start
+ $Waited = 0
+ While (-not (Get-Process -Id $NewKid.ProcessId -ErrorAction SilentlyContinue) -and ($waited -le 10)) { Start-Sleep -Seconds 1; $waited++ }
+ If (-not (Get-Process -Id $NewKid.ProcessId -ErrorAction SilentlyContinue)) {
+ "Failed to start new instance of $($Variables.Branding.ProductLabel)." | Tee-Object $UpdateLog -Append | Write-Message -Level Error
+ Return
+ }
+ }
+
+ $VersionTable = (Get-Content -Path ".\Version.txt").trim() | ConvertFrom-Json -AsHashtable
+ $VersionTable | Add-Member @{ AutoUpdated = ((Get-Date).DateTime) } -Force
+ $VersionTable | ConvertTo-Json | Out-File -FilePath ".\Version.txt" -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+
+ "Successfully updated $($UpdateVersion.Product) to version $($UpdateVersion.Version)." | Tee-Object $UpdateLog -Append | Write-Message -Level Verbose
+
+ # Display changelog
+ Notepad .\ChangeLog.txt
+
+ If ($NewKid.ProcessId) {
+ # Kill old instance
+ "Killing old instance..." | Tee-Object $UpdateLog -Append | Write-Message -Level Verbose
+ Start-Sleep -Seconds 2
+ If (Get-Process -Id $NewKid.ProcessId) { Stop-Process -Id $PID }
+ }
+}
+
+Function Start-LogReader {
+
+ If ((Test-Path $Config.SnakeTailExe -PathType Leaf -ErrorAction Ignore) -and (Test-Path $Config.SnakeTailConfig -PathType Leaf -ErrorAction Ignore)) {
+ $Variables.SnakeTailConfig = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Config.SnakeTailConfig)
+ $Variables.SnakeTailExe = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Config.SnakeTailExe)
+ If ($SnaketailProcess = (Get-CimInstance CIM_Process | Where-Object CommandLine -EQ "$($Variables.SnakeTailExe) $($Variables.SnakeTailConfig)")) {
+ # Activate existing Snaketail window
+ $MainWindowHandle = (Get-Process -Id $SnaketailProcess.ProcessId).MainWindowHandle
+ If (@($SnaketailMainWindowHandle).Count -eq 1) {
+ [Void][Win32]::ShowWindowAsync($MainWindowHandle, 6) # SW_MINIMIZE
+ [Void][Win32]::ShowWindowAsync($MainWindowHandle, 9) # SW_RESTORE
+ }
+ }
+ Else {
+ [Void](Invoke-CreateProcess -BinaryPath $Variables.SnakeTailExe -ArgumentList $Variables.SnakeTailConfig -WorkingDirectory (Split-Path $Variables.SnakeTailExe) -MinerWindowStyle "Normal" -Priority "-2" -EnvBlock $null -LogFile $null -JobName "Snaketail")
+ }
+ }
+}
+
+Function Update-ConfigFile {
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [String]$ConfigFile
+ )
+
+ # Changed config items
+ $Config.GetEnumerator().Name | ForEach-Object {
+ Switch ($_) {
+ "ActiveMinergain" { $Config.MinerSwitchingThreshold = $Config.$_; $Config.Remove($_) }
+ "AutoStart" {
+ If ($Config.$_ -eq $true) {
+ If ($Config.StartPaused -eq $true) { $Config.StartupMode = "Paused" }
+ Else { $Config.StartupMode = "Running" }
+ }
+ Else { $Config.StartupMode = "Idle" }
+ $Config.Remove($_)
+ $Config.Remove("StartPaused")
+ }
+ "AllowedBadShareRatio" { $Config.BadShareRatioThreshold = $Config.$_; $Config.Remove($_) }
+ "APIKEY" { $Config.MiningPoolHubAPIKey = $Config.$_; $Config.Remove($_) }
+ "BalancesTrackerConfigFile" { $Config.Remove($_) }
+ "DeductRejectedShares" { $Config.SubtractBadShares = $Config.$_; $Config.Remove($_) }
+ "EnableEarningsTrackerLog" { $Config.EnableBalancesLog = $Config.$_; $Config.Remove($_) }
+ "EstimateCorrection" { $Config.Remove($_) }
+ "Location" { $Config.Region = $Config.$_; $Config.Remove($_) }
+ "MPHAPIKey" { $Config.MiningPoolHubAPIKey = $Config.$_; $Config.Remove($_) }
+ "MPHUserName" { $Config.MiningPoolHubUserName = $Config.$_; $Config.Remove($_) }
+ "NoDualAlgoMining" { $Config.DisableDualAlgoMining = $Config.$_; $Config.Remove($_) }
+ "NoSingleAlgoMining" { $Config.DisableSingleAlgoMining = $Config.$_; $Config.Remove($_) }
+ "PasswordCurrency" { $Config.PayoutCurrency = $Config.$_; $Config.Remove($_) }
+ "PricePenaltyFactor" { $Config.EarningsAdjustmentFactor = $Config.$_; $Config.Remove($_) }
+ "ReadPowerUsage" { $Config.CalculatePowerCost = $Config.$_; $Config.Remove($_) }
+ "RunningMinerGainPct" { $Config.MinerSwitchingThreshold = $Config.$_; $Config.Remove($_) }
+ "ShowMinerWindows" { $Config.MinerWindowStyle = $Config.$_; $Config.Remove($_) }
+ "ShowMinerWindowsNormalWhenBenchmarking" { $Config.MinerWindowStyleNormalWhenBenchmarking = $Config.$_; $Config.Remove($_) }
+ "SSL" { $Config.Remove($_) }
+ "UserName" {
+ If (-not $Config.MiningPoolHubUserName) { $Config.MiningPoolHubUserName = $Config.$_ }
+ If (-not $Config.ProHashingUserName) { $Config.ProHashingUserName = $Config.$_ }
+ $Config.Remove($_)
+ }
+ "Wallet" {
+ If (-not $Config.Wallets) { $Config | Add-Member @{ Wallets = $Variables.AllCommandLineParameters.Wallets } }
+ $Config.Wallets.BTC = $Config.$_
+ $Config.Remove($_)
+ }
+ "WaitForMinerData" { $Config.Remove($_) }
+ "WarmupTime" { $Config.Remove($_) }
+ Default { If ($_ -notin @(@($Variables.AllCommandLineParameters.Keys) + @("PoolsConfig"))) { $Config.Remove($_) } } # Remove unsupported config item
+ }
+ }
+
+ # Add new config items
+ If ($New_Config_Items = $Variables.AllCommandLineParameters.Keys | Where-Object { $_ -notin $Config.Keys }) {
+ $New_Config_Items | Sort-Object Name | ForEach-Object {
+ $Value = $Variables.AllCommandLineParameters.$_
+ If ($Value -is [Switch]) { $Value = [Boolean]$Value }
+ $Config.$_ = $Value
+ }
+ Remove-Variable Value -ErrorAction Ignore
+ }
+
+ # Change currency names, remove mBTC
+ If ($Config.Currency -is [Array]) {
+ $Config.Currency = $Config.Currency | Select-Object -First 1
+ $Config.ExtraCurrencies = @($Config.Currency | Select-Object -Skip 1 | Where-Object { $_ -ne "mBTC" } | Select-Object)
+ }
+
+ # Move [PayoutCurrency] wallet to wallets
+ If ($PoolsConfig = Get-Content .\Config\PoolsConfig.json -ErrorAction Ignore | ConvertFrom-Json -ErrorAction Ignore) {
+ ($PoolsConfig | Get-Member -MemberType NoteProperty).Name | ForEach-Object {
+ If (-not $PoolsConfig.$_.Wallets -and $PoolsConfig.$_.Wallet) {
+ $PoolsConfig.$_ | Add-Member Wallets @{ "$($PoolsConfig.$_.PayoutCurrency)" = $PoolsConfig.$_.Wallet } -ErrorAction Ignore
+ $PoolsConfig.$_.PSObject.Members.Remove("Wallet")
+ }
+ }
+ $PoolsConfig | ConvertTo-Json | Out-File -FilePath .\Config\PoolsConfig.json -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+ }
+
+ # Rename MPH to MiningPoolHub
+ $Config.PoolName = $Config.PoolName -replace "MPH", "MiningPoolHub"
+ $Config.PoolName = $Config.PoolName -replace "MPHCoins", "MiningPoolHubCoins"
+
+ # Available regions have changed
+ If (-not (Get-Region $Config.Region -List)) {
+ $OldRegion = $Config.Region
+ # Write message about new mining regions
+ Switch ($Config.Region) {
+ "Brazil" { $Config.Region = "USA West" }
+ "Europe" { $Config.Region = "Europe West" }
+ "Europe East" { $Config.Region = "Europe North" }
+ "HongKong" { $Config.Region = "Asia" }
+ "India" { $Config.Region = "Asia" }
+ "Japan" { $Config.Region = "Japan" }
+ "Russia" { $Config.Region = "Russia" }
+ "US" { $Config.Region = "USA West" }
+ Default { $Config.Region = "Europe West" }
+ }
+ Write-Message -Level Warn "Available mining locations have changed ($OldRegion -> $($Config.Region)). Please verify your configuration."
+ Remove-Variable OldRegion
+ }
+
+ # Remove AHashPool
+ $Config.PoolName = $Config.PoolName | Where-Object { $_ -notlike "AhashPool*" }
+
+ $Config | Add-Member ConfigFileVersion ($Variables.Branding.Version.ToString()) -Force
+ Write-Config -ConfigFile $ConfigFile
+ "Updated configuration file '$($ConfigFile)' to version $($Variables.Branding.Version.ToString())." | Write-Message -Level Verbose
+ Remove-Variable New_Config_Items -ErrorAction Ignore
+}
+
+Function Remove-OrphanedMinerStats {
+
+ $MinerNames = @(Get-ChildItem ".\Miners\*.ps1").BaseName
+ $TempStatNames = @($Stats.Keys | Where-Object { $_ -match "_Hashrate$|_PowerUsage$" } | Where-Object { (($_ -split "-" | Select-Object -First 2) -join "-") -notin $MinerNames})
+ If ($TempStatNames) { $TempStatNames | ForEach-Object { Remove-Stat $_ } }
+
+ $TempStatNames
+}
+
+Function Test-Prime {
+
+ Param(
+ [Parameter(Mandatory = $true)]
+ [Double]$Number
+ )
+
+ For ([Int64]$i = 2; $i -lt [Int64][Math]::Pow($Number, 0.5); $i++) { If ($Number % $i -eq 0) { Return $false } }
+
+ Return $true
+}
+
+Function Get-DAGsize {
+
+ Param(
+ [Parameter(Mandatory = $false)]
+ [Double]$Block = ((Get-Date) - [DateTime]"07/31/2015").Days * 6400,
+ [Parameter(Mandatory = $false)]
+ [String]$Coin
+ )
+
+ Switch ($Coin) {
+ "ETC" { $Epoch_Length = If ($Block -ge 11700000 ) { 60000 } Else { 30000 } }
+ "RVN" { $Epoch_Length = 7500 }
+ Default { $Epoch_Length = 30000 }
+ }
+
+ $DATASET_BYTES_INIT = [Math]::Pow(2, 30)
+ $DATASET_BYTES_GROWTH = [Math]::Pow(2, 23)
+ $MIX_BYTES = 128
+
+ $Size = $DATASET_BYTES_INIT + $DATASET_BYTES_GROWTH * [Math]::Floor($Block / $EPOCH_LENGTH)
+ $Size -= $MIX_BYTES
+ While (-not (Test-Prime ($Size / $MIX_BYTES))) { $Size -= 2 * $MIX_BYTES }
+
+ Return [Int64]$Size
+}
+
+Function Out-DataTable {
+
+ <#
+ .SYNOPSIS
+ Creates a DataTable for an object
+ .DESCRIPTION
+ Creates a DataTable based on an objects properties.
+ .INPUTS
+ Object
+ Any object can be piped to Out-DataTable
+ .OUTPUTS
+ System.Data.DataTable
+ .EXAMPLE
+ $dt = Get-psdrive| Out-DataTable
+ This example creates a DataTable from the properties of Get-psdrive and assigns output to $dt variable
+ .NOTES
+ Adapted from script by Marc van Orsouw see link
+ Version History
+ v1.0 - Chad Miller - Initial Release
+ v1.1 - Chad Miller - Fixed Issue with Properties
+ v1.2 - Chad Miller - Added setting column datatype by property as suggested by emp0
+ v1.3 - Chad Miller - Corrected issue with setting datatype on empty properties
+ v1.4 - Chad Miller - Corrected issue with DBNull
+ v1.5 - Chad Miller - Updated example
+ v1.6 - Chad Miller - Added column datatype logic with default to string
+ v1.7 - Chad Miller - Fixed issue with IsArray
+ .LINK
+ http://thepowershellguy.com/blogs/posh/archive/2007/01/21/powershell-gui-scripblock-monitor-script.aspx
+ #>
+
+ [CmdletBinding()]
+ Param(
+ [Parameter(
+ Position = 0,
+ Mandatory = $true,
+ ValueFromPipeline = $true
+ )]
+ [PSObject[]]$InputObject
+ )
+
+ Begin {
+ $DT = New-Object Data.datatable
+ $First = $true
+ }
+ Process {
+ ForEach ($Object in $InputObject) {
+ $DR = $DT.NewRow()
+ ForEach ($Property in $Object.PSObject.Properties) {
+ If ($First) {
+ $Col = New-Object Data.DataColumn
+ $Col.ColumnName = $Property.Name.ToString()
+ If ($Property.Value) {
+ If ($Property.Value -isnot [System.DBNull]) {
+ $Col.DataType = [System.Type]::GetType($Property.TypeNameOfValue).Name
+ }
+ }
+ $DT.Columns.Add($Col)
+ }
+ If ($Property.GetType().IsArray) {
+ $DR.Item($Property.Name) = $Property.Value | ConvertTo-Xml -As String -NoTypeInformation -Depth 1
+ }
+ Else {
+ $DR.Item($Property.Name) = $Property.Value
+ }
+ }
+ $DT.Rows.Add($DR)
+ $First = $false
+ }
+ }
+
+ End {
+ Write-Output @(,($dt))
+ }
+}
diff --git a/Includes/MinerAPIs/Cast.ps1 b/Includes/MinerAPIs/Cast.ps1
new file mode 100644
index 0000000000..6825e8aab0
--- /dev/null
+++ b/Includes/MinerAPIs/Cast.ps1
@@ -0,0 +1,66 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: Cast.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class Cast : Miner {
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = "http://localhost:$($this.Port)/"
+
+ Try {
+ $Data = Invoke-RestMethod -Uri $Request -TimeoutSec $Timeout
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = [String]$this.Algorithm[0]
+ $HashRate_Value = [Double]($Data.devices.hash_rate | Measure-Object -Sum).Sum / 1000
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]$Data.shares.num_accepted
+ $Shares_Rejected = [Int64]($Data.shares.num_rejected + $Data.shares.num_rejected + $Data.shares.num_network_fail + $Data.shares.num_outdated)
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
diff --git a/Includes/MinerAPIs/Ccminer.ps1 b/Includes/MinerAPIs/Ccminer.ps1
new file mode 100644
index 0000000000..fc8f409199
--- /dev/null
+++ b/Includes/MinerAPIs/Ccminer.ps1
@@ -0,0 +1,69 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: CCminer.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class Ccminer : Miner {
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = "summary"
+ $Response = ""
+
+ Try {
+ $Response = Invoke-TcpRequest -Server "localhost" -Port $this.Port -Request $Request -Timeout $Timeout -ErrorAction Stop
+ $Data = $Response -split ";" | ConvertFrom-StringData -ErrorAction Stop
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = [String]$this.Algorithm[0]
+ $HashRate_Value = [Double]$Data.KHS * 1000
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]($Data.ACC | Measure-Object -Sum).Sum
+ $Shares_Rejected = [Int64]($Data.REJ | Measure-Object -Sum).Sum
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
+
diff --git a/Includes/MinerAPIs/Dstm.ps1 b/Includes/MinerAPIs/Dstm.ps1
new file mode 100644
index 0000000000..50edcea8ba
--- /dev/null
+++ b/Includes/MinerAPIs/Dstm.ps1
@@ -0,0 +1,70 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: Dstm.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class Dstm : Miner {
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = @{ id = 1; method = "getstat" } | ConvertTo-Json -Compress
+ $Response = ""
+
+ Try {
+ $Response = Invoke-TcpRequest -Server "localhost" -Port $this.Port -request $Request -Timeout $Timeout -ErrorAction Stop
+ $Data = $Response | ConvertFrom-Json -ErrorAction Stop
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = [String]$this.Algorithm[0]
+ $HashRate_Value = [Double]($Data.result.speed_sps | Measure-Object -Sum).Sum
+ If (-not $HashRate_Value) { $HashRate_Value = [Double]($Data.result.sol_ps | Measure-Object -Sum).Sum } #fix
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]($Data.result.accepted_shares | Measure-Object -Sum).Sum
+ $Shares_Rejected = [Int64]($Data.result.rejected_shares | Measure-Object -Sum).Sum
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
+
diff --git a/Includes/MinerAPIs/Eminer.ps1 b/Includes/MinerAPIs/Eminer.ps1
new file mode 100644
index 0000000000..0a27787c8e
--- /dev/null
+++ b/Includes/MinerAPIs/Eminer.ps1
@@ -0,0 +1,67 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: EMiner.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class Eminer : Miner {
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = "http://localhost:$($this.Port)/api/v1/stats"
+
+ Try {
+ $Data = Invoke-RestMethod -Uri $Request -TimeoutSec $Timeout
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = [String]$this.Algorithm[0]
+ $HashRate_Value = [Double]$Data.total_hashrate_mean
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]$Data.found_solutions
+ $Shares_Rejected = [Int64]($Data.invalid_solutions + $Data.rejected_solutions)
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
+
diff --git a/Includes/MinerAPIs/EthMiner.ps1 b/Includes/MinerAPIs/EthMiner.ps1
new file mode 100644
index 0000000000..9f14c48550
--- /dev/null
+++ b/Includes/MinerAPIs/EthMiner.ps1
@@ -0,0 +1,87 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: EthMiner.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class EthMiner : Miner {
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = @{ id = 1; jsonrpc = "2.0"; method = "miner_getstat1" } | ConvertTo-Json -Compress
+ $Response = ""
+
+ Try {
+ $Response = Invoke-TcpRequest -Server "localhost" -Port $this.Port -Request $Request -Timeout $Timeout -ErrorAction Stop
+ $Data = $Response | ConvertFrom-Json -ErrorAction Stop
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = [String]$this.Algorithm[0]
+ $HashRate_Value = [Double]($Data.result[2] -split ";")[0]
+ If ($Data.result[0] -notmatch "^TT-Miner") {
+ If ($HashRate_Name -eq "EtcHash") { $HashRate_Value *= 1000 }
+ ElseIf ($HashRate_Name -eq "Ethash") { $HashRate_Value *= 1000 }
+ ElseIf ($HashRate_Name -eq "EthashLowMem") { $HashRate_Value *= 1000 }
+ ElseIf ($HashRate_Name -eq "UbqHash") { $HashRate_Value *= 1000 }
+ }
+ If ($HashRate_Name -eq "Neoscrypt") { $HashRate_Value *= 1000 }
+ ElseIf ($HashRate_Name -eq "BitcoinInterest") { $HashRate_Value *= 1000 }
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]($Data.result[2] -split ";")[1]
+ $Shares_Rejected = [Int64]($Data.result[2] -split ";")[2]
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($HashRate_Name = [String]($this.Algorithm -ne $HashRate_Name)) { # Dual algo mining
+ $HashRate_Value = [Double]($Data.result[4] -split ";")[0]
+ If ($this.Algorithm -eq "Blake2s") { $HashRate_Value *= 1000 }
+ If ($this.Algorithm -eq "Keccak") { $HashRate_Value *= 1000 }
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares_Accepted = [Int64]($Data.result[4] -split ";")[1]
+ $Shares_Rejected = [Int64]($Data.result[4] -split ";")[2]
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+ }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
diff --git a/Includes/MinerAPIs/FireIce.ps1 b/Includes/MinerAPIs/FireIce.ps1
new file mode 100644
index 0000000000..9fcf03d192
--- /dev/null
+++ b/Includes/MinerAPIs/FireIce.ps1
@@ -0,0 +1,136 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: FireIce.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class Fireice : Miner {
+ CreateConfigFiles() {
+ Try {
+ $Parameters = $this.Arguments | ConvertFrom-Json -ErrorAction SilentlyContinue
+ $ConfigFile = "$(Split-Path $this.Path)\$($Parameters.ConfigFile.FileName)"
+ $PoolFile = "$(Split-Path $this.Path)\$($Parameters.PoolFile.FileName)"
+ $PlatformThreadsConfigFile = "$(Split-Path $this.Path)\$($Parameters.PlatformThreadsConfigFileName)"
+ $MinerThreadsConfigFile = "$(Split-Path $this.Path)\$($Parameters.MinerThreadsConfigFileName)"
+ $ThreadsConfig = ""
+
+ #Write pool config file, overwrite every time
+ ($Parameters.PoolFile.Content | ConvertTo-Json -Depth 10) -replace '^{' -replace '}$', ',' | Out-File -FilePath $PoolFile -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+ #Write config file, keep existing file to preserve user custom config
+ If (-not (Test-Path -Path $ConfigFile -PathType Leaf)) { ($Parameters.ConfigFile.Content | ConvertTo-Json -Depth 10) -replace '^{' -replace '}$' | Out-File -FilePath $ConfigFile -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue}
+
+ #Check if we have a valid hw file for all installed hardware. If hardware / device order has changed we need to re-create the config files.
+ If (-not (Test-Path -Path $PlatformThreadsConfigFile -PathType Leaf)) {
+ If (Test-Path -Path "$(Split-Path $this.Path)\$MinerThreadsConfigFile" -PathType Leaf) {
+ #Remove old config files, thread info is no longer valid
+ Write-Message -Level Warn "Hardware change detected. Deleting existing configuration files for miner $($this.Info)'."
+ Remove-Item -Path "$(Split-Path $this.Path)\$MinerThreadsConfigFile" -Force -ErrorAction SilentlyContinue
+ }
+
+ #Temporarily start miner with empty thread conf file. The miner will then create a hw config file with default threads info for all platform hardware
+ $this.Process = Invoke-CreateProcess -BinaryPath $this.Path -ArgumentList $Parameters.HwDetectArguments -WorkingDirectory (Split-Path $this.Path) -MinerWindowStyle $this.MinerWindowStyle -Priority $this.ProcessPriority -EnvBlock $this.Environment -JobName $this.Info -LogFile $this.LogFile
+
+ If ($this.Process) {
+ For ($WaitForThreadsConfig = 0; $WaitForThreadsConfig -le 60; $WaitForThreadsConfig++) {
+ $this.ProcessId = [Int32]((Get-CIMInstance CIM_Process | Where-Object { $_.ExecutablePath -eq $this.Path -and $_.CommandLine -like "*$($this.Path)*$($Parameters.HwDetectArguments)*" }).ProcessId)
+ If ($this.ProcessId -and (Test-Path -Path $PlatformThreadsConfigFile -PathType Leaf)) {
+ #Read hw config created by miner
+ $ThreadsConfig = (Get-Content -Path $PlatformThreadsConfigFile) -replace '^\s*//.*' | Out-String
+ #Set bfactor to 11 (default is 6 which makes PC unusable)
+ $ThreadsConfig = $ThreadsConfig -replace '"bfactor"\s*:\s*\d,', '"bfactor" : 11,'
+ #Reformat to proper json
+ $ThreadsConfigJson = "{$($ThreadsConfig -replace '\/\*.*' -replace '\*\/' -replace '\*.+' -replace '\s' -replace ',\},]', '}]' -replace ',\},\{', '},{' -replace '},]', '}]' -replace ',$', '')}" | ConvertFrom-Json
+ #Keep one instance per gpu config
+ $ThreadsConfigJson | Add-Member gpu_threads_conf ($ThreadsConfigJson.gpu_threads_conf | Sort-Object -Property Index -Unique) -Force
+ #Write json file
+ $ThreadsConfigJson | ConvertTo-Json -Depth 10 | Out-File -FilePath $PlatformThreadsConfigFile -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+ Break
+ }
+ Start-Sleep -Milliseconds 500
+ }
+ Stop-Process -Id $this.ProcessId -Force -ErrorAction Ignore
+ $this.Process = $null
+ }
+ Else {
+ Write-Message -Level Error "Running temporary miner failed - cannot create threads config file '$($this.Info)' [Error: '$($Error | Select-Object -First 1)']."
+ Return
+ }
+ }
+ If (-not (Test-Path $MinerThreadsConfigFile -PathType Leaf)) {
+ #Retrieve hw config from platform config file
+ $ThreadsConfigJson = Get-Content -Path $PlatformThreadsConfigFile | ConvertFrom-Json -ErrorAction SilentlyContinue
+ #Filter index for current cards and apply threads
+ $ThreadsConfigJson | Add-Member gpu_threads_conf ([Array]($ThreadsConfigJson.gpu_threads_conf | Where-Object { $Parameters.Devices -contains $_.Index }) * $Parameters.Threads) -Force
+ #Create correct numer of CPU threads
+ $ThreadsConfigJson | Add-Member cpu_threads_conf ([Array]$ThreadsConfigJson.cpu_threads_conf * $Parameters.Threads) -Force
+ #Write config file
+ ($ThreadsConfigJson | ConvertTo-Json -Depth 10) -replace '^{' -replace '}$' | Out-File -FilePath $MinerThreadsConfigFile -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+ }
+ }
+ catch {
+ Write-Message -Level Error "Creating miner config files for '$($this.Info)' failed [Error: '$($Error | Select-Object -First 1)']."
+ Return
+ }
+ }
+
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = "http://localhost:$($this.Port)/api.json"
+
+ Try {
+ $Data = Invoke-RestMethod -Uri $Request -TimeoutSec $Timeout
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = [String]$this.Algorithm[0]
+ $HashRate_Value = [Double]$Data.hashrate.total[0]
+ If (-not $HashRate_Value) { $HashRate_Value = [Double]$Data.hashrate.total[1] } #fix
+ If (-not $HashRate_Value) { $HashRate_Value = [Double]$Data.hashrate.total[2] } #fix
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]$Data.results.shares_good
+ $Shares_Rejected = [Int64]($Data.results.shares_total - $Data.results.shares_good)
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
diff --git a/Includes/MinerAPIs/Gminer.ps1 b/Includes/MinerAPIs/Gminer.ps1
new file mode 100644
index 0000000000..46c8a1d0dd
--- /dev/null
+++ b/Includes/MinerAPIs/Gminer.ps1
@@ -0,0 +1,77 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: GMiner.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class Gminer : Miner {
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = "http://localhost:$($this.Port)/stat"
+
+ Try {
+ $Data = Invoke-RestMethod -Uri $Request -TimeoutSec $Timeout
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = [String]$this.Algorithm[0]
+ $HashRate_Value = [Double]($Data.devices.speed | Measure-Object -Sum).Sum
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]($Data.total_accepted_shares)
+ $Shares_Rejected = [Int64]($Data.total_rejected_shares)
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($this.Algorithm[1]) {
+ $HashRate_Name = [String]$this.Algorithm[1]
+ $HashRate_Value = [Double]($Data.devices.speed2 | Measure-Object -Sum).Sum
+ $Shares_Accepted = [Int64]($Data.total_accepted_shares2)
+ $Shares_Rejected = [Int64]($Data.total_rejected_shares2)
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+ }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
+
diff --git a/Includes/MinerAPIs/LogFile.ps1 b/Includes/MinerAPIs/LogFile.ps1
new file mode 100644
index 0000000000..a8da5cb0c4
--- /dev/null
+++ b/Includes/MinerAPIs/LogFile.ps1
@@ -0,0 +1,96 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: LogFile.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class LogFile : Miner {
+ [Object]GetMinerData () {
+
+ $Sample = [PSCustomObject]@{ }
+
+ If (Test-Path $this.LogFile -PathType Leaf) {
+
+ $Lines = Get-Path $this.LogFile
+ Remove-Item -Path $this.LogFile -Force
+
+ $Lines | ForEach-Object {
+
+ $Line = $_ -replace "`n|`r", ""
+ $Line_Simple = $Line -replace "\x1B\[[0-?]*[ -/]*[@-~]", ""
+
+ If ($Line_Simple) {
+
+ $HashRate = [PSCustomObject]@{ }
+ $Shares = [PSCustomObject]@{ }
+
+ $PowerUsage = 0
+ $HashRate_Name = ""
+
+ If ($Line_Simple -match "/s") {
+ $Words = $Line_Simple -split " "
+
+ $Words -match "/s$" | ForEach-Object {
+
+ If ($HashRate_Name -and ($this.Algorithm[1] -gt 1)) { $HashRate_Name = [String]$this.Algorithm[1] } Else { $HashRate_Name = [String]$this.Algorithm[0] }
+
+ If (($Words | Select-Object -Index $Words.IndexOf($_)) -match "^((?:\d*\.)?\d+)(.*)$") {
+ $HashRate_Value = ($matches | Select-Object -Index 1) -as [Decimal]
+ $HashRate_Unit = ($matches | Select-Object -Index 2)
+ }
+ Else {
+ $HashRate_Value = ($Words | Select-Object -Index ($Words.IndexOf($_) - 1)) -as [Decimal]
+ $HashRate_Unit = ($Words | Select-Object -Index $Words.IndexOf($_))
+ }
+
+ Switch -wildcard ($HashRate_Unit) {
+ "kh/s*" { $HashRate_Value *= [Math]::Pow(1000, 1) }
+ "mh/s*" { $HashRate_Value *= [Math]::Pow(1000, 2) }
+ "gh/s*" { $HashRate_Value *= [Math]::Pow(1000, 3) }
+ "th/s*" { $HashRate_Value *= [Math]::Pow(1000, 4) }
+ "ph/s*" { $HashRate_Value *= [Math]::Pow(1000, 5) }
+ }
+ $Shares_Accepted = [Int64]0
+ $Shares_Rejected = [Int64]0
+
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+ }
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ }
+ }
+ }
+ }
+ Return $Sample
+ }
+}
\ No newline at end of file
diff --git a/Includes/MinerAPIs/MiniZ.ps1 b/Includes/MinerAPIs/MiniZ.ps1
new file mode 100644
index 0000000000..6c82bd4cad
--- /dev/null
+++ b/Includes/MinerAPIs/MiniZ.ps1
@@ -0,0 +1,69 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: MiniZ.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class MiniZ : Miner {
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = '{ "id":"0", "method":"getstat" }'
+ $Response = ""
+
+ Try {
+ $Response = Invoke-TcpRequest "localhost" -Port $this.Port -Request $Request -Timeout $Timeout -ReadToEnd $true -ErrorAction Stop
+ $Data = $Response.Substring($Response.IndexOf("{")) | ConvertFrom-Json -ErrorAction Stop
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = [String]$this.Algorithm[0]
+ $HashRate_Value = [Double]($Data.result.speed_sps | Measure-Object -Sum).Sum
+ If (-not $HashRate_Value) { $HashRate_Value = [Double]($Data.result.sol_ps | Measure-Object -Sum).Sum } #fix
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]($Data.result.accepted_shares | Measure-Object -Sum).Sum
+ $Shares_Rejected = [Int64]($Data.result.rejected_shares | Measure-Object -Sum).Sum
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
diff --git a/Includes/MinerAPIs/NBMiner.ps1 b/Includes/MinerAPIs/NBMiner.ps1
new file mode 100644
index 0000000000..bbf6a7c348
--- /dev/null
+++ b/Includes/MinerAPIs/NBMiner.ps1
@@ -0,0 +1,77 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: NBMiner.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class NBMiner : Miner {
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = "http://localhost:$($this.Port)/api/v1/status"
+
+ Try {
+ $Data = Invoke-RestMethod -Uri $Request -TimeoutSec $Timeout
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = $this.Algorithm | Select-Object -Last 1
+ $HashRate_Value = [Double]$Data.miner.total_hashrate_raw
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]$Data.stratum.accepted_shares
+ $Shares_Rejected = [Int64]$Data.stratum.rejected_shares
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($Data.stratum.dual_mine) {
+ $HashRate_Name = [String]($this.Algorithm -ne $HashRate_Name)
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$Data.miner.total_hashrate2_raw }
+
+ $Shares_Accepted = [Int64]$Data.stratum.accepted_shares2
+ $Shares_Rejected = [Int64]$Data.stratum.rejected_shares2
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+ }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
+
+
diff --git a/Includes/MinerAPIs/NanoMiner.ps1 b/Includes/MinerAPIs/NanoMiner.ps1
new file mode 100644
index 0000000000..948e4afdf8
--- /dev/null
+++ b/Includes/MinerAPIs/NanoMiner.ps1
@@ -0,0 +1,90 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: NanoMiner.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class NanoMiner : Miner {
+ CreateConfigFiles() {
+ $Parameters = $this.Arguments | ConvertFrom-Json -ErrorAction SilentlyContinue
+
+ Try {
+ $ConfigFile = "$(Split-Path $this.Path)\$($Parameters.ConfigFile.FileName)"
+ #Write config files. Do not overwrite existing files to preserve optional manual customization
+ If (-not (Test-Path $ConfigFile -PathType Leaf)) {
+ $Parameters.ConfigFile.Content | Out-File -FilePath $ConfigFile -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+ }
+ }
+ Catch {
+ Write-Message -Level Error "Creating miner config files for '$($this.Info)' failed [Error: '$($Error | Select-Object -First 1)']."
+ Return
+ }
+ }
+
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = "http://localhost:$($this.Port)/stats"
+
+ Try {
+ $Data = Invoke-RestMethod -Uri $Request -TimeoutSec $Timeout
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = $this.Algorithm[0]
+ $HashRate_Value = [Double]0
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]0
+ $Shares_Rejected = [Int64]0
+
+ $Data.Algorithms | ForEach-Object { ($_ | Get-Member -MemberType NoteProperty).Name } | Select-Object -Unique | ForEach-Object {
+ $HashRate_Value = [Double]($Data.Algorithms.$_.Total.Hashrate | Measure-Object -Sum).Sum
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares_Accepted = [Int64]($Data.Algorithms.$_.Total.Accepted | Measure-Object -Sum).Sum
+ $Shares_Rejected = [Int64]($Data.Algorithms.$_.Total.Denied | Measure-Object -Sum).Sum
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+ }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
+
diff --git a/Includes/MinerAPIs/Nheq.ps1 b/Includes/MinerAPIs/Nheq.ps1
new file mode 100644
index 0000000000..fb826e2853
--- /dev/null
+++ b/Includes/MinerAPIs/Nheq.ps1
@@ -0,0 +1,68 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: Nheq.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class Nheq : Miner {
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Response = ""
+
+ Try {
+ $Response = Invoke-TcpRequest -Server "localhost" -Port $this.Port -Request "status" -Timeout $Timeout
+ $Data = $Response | ConvertFrom-Json
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = [String]$this.Algorithm[0]
+ $HashRate_Value = [Double]($Data.result.speed_ips | Measure-Object -Sum).Sum * 1e6
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]($Data.result.accepted_per_minute | Measure-Object -Sum).Sum
+ $Shares_Rejected = [Int64]($Data.result.rejected_per_minute | Measure-Object -Sum).Sum
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
+
diff --git a/Includes/MinerAPIs/NoAPI.ps1 b/Includes/MinerAPIs/NoAPI.ps1
new file mode 100644
index 0000000000..62621869cf
--- /dev/null
+++ b/Includes/MinerAPIs/NoAPI.ps1
@@ -0,0 +1,60 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: LogFile.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class NoAPI : Miner {
+ [Object]GetMinerData () {
+
+ [Double]$HashRate_Value = 0
+
+ # This will 'fake' has rate data, VertMiner currently has no API to retrieve live stat information
+ $StaticHashRates = Get-Content "$(Split-Path $this.Path)\Hashrates.json" -ErrorAction Stop | ConvertFrom-Json | Select-Object
+ $HashRate_Value = [Double]$StaticHashRates.($this.Devices.Name -join ',')
+
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = $this.Algorithm | Select-Object -Last 1
+ $HashRate | Add-Member @{ $HashRate_Name = $HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]0
+ $Shares_Rejected = [Int64]0
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
\ No newline at end of file
diff --git a/Includes/MinerAPIs/SRBMiner.ps1 b/Includes/MinerAPIs/SRBMiner.ps1
new file mode 100644
index 0000000000..b6b7386a3d
--- /dev/null
+++ b/Includes/MinerAPIs/SRBMiner.ps1
@@ -0,0 +1,79 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: SRBminer.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class SRBMiner : Miner {
+
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = "http://localhost:$($this.Port)"
+
+ Try {
+ $Data = Invoke-RestMethod -Uri $Request -TimeoutSec $Timeout
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = [String]$this.Algorithm[0]
+ $HashRate_Value = [Double]0
+ If ($Data.algorithms) { $HashRate_Value = [Double]$Data.algorithms[0].hashrate.gpu.total }
+ If (-not $HashRate_Value) { $HashRate_Value = [Double]$Data.algorithms[0].hashrate.cpu.total }
+ If (-not $HashRate_Value) { $HashRate_Value = [Double]$Data.algorithms[0].hashrate.now }
+ If (-not $HashRate_Value) { $HashRate_Value = [Double]$Data.hashrate_total_now }
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]0
+ $Shares_Rejected = [Int64]0
+ If ($Data.algorithms) {
+ $Shares_Accepted = [Int64]$Data.algorithms[0].shares.accepted
+ $Shares_Rejected = [Int64]$Data.algorithms[0].shares.rejected
+ }
+ Else {
+ $Shares_Accepted = [Int64]$Data.shares.accepted
+ $Shares_Rejected = [Int64]$Data.shares.rejected
+ }
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
diff --git a/Includes/MinerAPIs/TeamBlackMiner.ps1 b/Includes/MinerAPIs/TeamBlackMiner.ps1
new file mode 100644
index 0000000000..f1aa1aa138
--- /dev/null
+++ b/Includes/MinerAPIs/TeamBlackMiner.ps1
@@ -0,0 +1,67 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: lolMiner.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class TeamBlackMiner : Miner {
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = "http://localhost:$($this.Port)/miner"
+
+ Try {
+ $Data = Invoke-RestMethod -Uri $Request -TimeoutSec $Timeout
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = [String]$this.Algorithm[0]
+ $HashRate_Value = [Double]($Data.total_hashrate)
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]$Data.total_accepted
+ $Shares_Rejected = [Int64]$Data.total_rejected
+ $Shares_Stale = [Int64]$Data.total_sta
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, ($Shares_Rejected + $Shares_Stale), ($Shares_Accepted + $Shares_Rejected + $Shares_Stale)) }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
diff --git a/Includes/MinerAPIs/Trex.ps1 b/Includes/MinerAPIs/Trex.ps1
new file mode 100644
index 0000000000..f4b9a60bfb
--- /dev/null
+++ b/Includes/MinerAPIs/Trex.ps1
@@ -0,0 +1,78 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: Trex.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class Trex : Miner {
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = "http://localhost:$($this.Port)/summary"
+
+ Try {
+ $Data = Invoke-RestMethod -Uri $Request -TimeoutSec $Timeout
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = [String]$this.Algorithm[0]
+ $HashRate_Value = [Double]$Data.hashrate_minute
+ If (-not $Data.hashrate_minute) { $HashRate_Value = [Double]$Data.hashrate }
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]$Data.accepted_count
+ $Shares_Rejected = [Int64]$Data.rejected_count
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($HashRate_Name = [String]($this.Algorithm -ne $HashRate_Name)) { # Dual algo mining
+ $HashRate_Value = [Double]$Data.dual_stat.hashrate_minute
+ If (-not $HashRate_Value) { $HashRate_Value = [Double]$Data.dual_stat.hashrate }
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares_Accepted = [Int64]$Data.dual_stat.accepted_count
+ $Shares_Rejected = [Int64]$Data.dual_stat.rejected_count
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+ }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
+
diff --git a/Includes/MinerAPIs/Wrapper.ps1 b/Includes/MinerAPIs/Wrapper.ps1
new file mode 100644
index 0000000000..e66f9ee768
--- /dev/null
+++ b/Includes/MinerAPIs/Wrapper.ps1
@@ -0,0 +1,93 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: Xgminer.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class Wrapper : Miner {
+ [Object]GetMinerData () {
+
+ $Sample = [PSCustomObject]@{ }
+
+ If ($this.Process.HasMoreData) {
+
+ $this.Process | Receive-Job | ForEach-Object {
+
+ $Line = $_ -replace "`n|`r", ""
+ $Line_Simple = $Line -replace "\x1B\[[0-?]*[ -/]*[@-~]", ""
+
+ If ($Line_Simple) {
+
+ $HashRate = [PSCustomObject]@{ }
+ $Shares = [PSCustomObject]@{ }
+
+ $PowerUsage = 0
+ $HashRate_Name = ""
+
+ If ($Line_Simple -match "/s") {
+ $Words = $Line_Simple -split " "
+
+ $Words -match "/s$" | ForEach-Object {
+
+ If ($HashRate_Name -and ($this.Algorithm[1] -gt 1)) { $HashRate_Name = [String]$this.Algorithm[1] } Else { $HashRate_Name = [String]$this.Algorithm[0] }
+
+ If (($Words | Select-Object -Index $Words.IndexOf($_)) -match "^((?:\d*\.)?\d+)(.*)$") {
+ $HashRate_Value = ($matches | Select-Object -Index 1) -as [Decimal]
+ $HashRate_Unit = ($matches | Select-Object -Index 2)
+ }
+ Else {
+ $HashRate_Value = ($Words | Select-Object -Index ($Words.IndexOf($_) - 1)) -as [Decimal]
+ $HashRate_Unit = ($Words | Select-Object -Index $Words.IndexOf($_))
+ }
+
+ Switch -wildcard ($HashRate_Unit) {
+ "kh/s*" { $HashRate_Value *= [Math]::Pow(1000, 1) }
+ "mh/s*" { $HashRate_Value *= [Math]::Pow(1000, 2) }
+ "gh/s*" { $HashRate_Value *= [Math]::Pow(1000, 3) }
+ "th/s*" { $HashRate_Value *= [Math]::Pow(1000, 4) }
+ "ph/s*" { $HashRate_Value *= [Math]::Pow(1000, 5) }
+ }
+ $Shares_Accepted = [Int64]0
+ $Shares_Rejected = [Int64]0
+
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+ }
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ }
+ }
+ }
+ }
+ Return $Sample
+ }
+}
\ No newline at end of file
diff --git a/Includes/MinerAPIs/Xgminer.ps1 b/Includes/MinerAPIs/Xgminer.ps1
new file mode 100644
index 0000000000..59f3ac56ca
--- /dev/null
+++ b/Includes/MinerAPIs/Xgminer.ps1
@@ -0,0 +1,119 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: Xgminer.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class Xgminer : Miner {
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = @{ command = "summary"; parameter = "" } | ConvertTo-Json -Compress
+ $Response = ""
+
+ Try {
+ $Response = Invoke-TcpRequest -Server "localhost" -Port $this.Port -Request $Request -Timeout $Timeout -ErrorAction Stop
+ $Data = $Response.Substring($Response.IndexOf("{"), $Response.LastIndexOf("}") - $Response.IndexOf("{") + 1) -replace " ", "_" | ConvertFrom-Json -ErrorAction Stop
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = [String]$this.Algorithm[0]
+ $HashRate_Value = If ($Data.SUMMARY.HS_5s) { [Double]$Data.SUMMARY.HS_5s * [Math]::Pow(1000, 0) }
+ elseif ($Data.SUMMARY.KHS_5s) { [Double]$Data.SUMMARY.KHS_5s * [Math]::Pow(1000, 1) }
+ elseif ($Data.SUMMARY.MHS_5s) { [Double]$Data.SUMMARY.MHS_5s * [Math]::Pow(1000, 2) }
+ elseif ($Data.SUMMARY.GHS_5s) { [Double]$Data.SUMMARY.GHS_5s * [Math]::Pow(1000, 3) }
+ elseif ($Data.SUMMARY.THS_5s) { [Double]$Data.SUMMARY.THS_5s * [Math]::Pow(1000, 4) }
+ elseif ($Data.SUMMARY.PHS_5s) { [Double]$Data.SUMMARY.PHS_5s * [Math]::Pow(1000, 5) }
+ elseif ($Data.SUMMARY.KHS_30s) { [Double]$Data.SUMMARY.KHS_30s * [Math]::Pow(1000, 1) }
+ elseif ($Data.SUMMARY.MHS_30s) { [Double]$Data.SUMMARY.MHS_30s * [Math]::Pow(1000, 2) }
+ elseif ($Data.SUMMARY.GHS_30s) { [Double]$Data.SUMMARY.GHS_30s * [Math]::Pow(1000, 3) }
+ elseif ($Data.SUMMARY.THS_30s) { [Double]$Data.SUMMARY.THS_30s * [Math]::Pow(1000, 4) }
+ elseif ($Data.SUMMARY.PHS_30s) { [Double]$Data.SUMMARY.PHS_30s * [Math]::Pow(1000, 5) }
+ elseif ($Data.SUMMARY.HS_av) { [Double]$Data.SUMMARY.HS_av * [Math]::Pow(1000, 0) }
+ elseif ($Data.SUMMARY.KHS_av) { [Double]$Data.SUMMARY.KHS_av * [Math]::Pow(1000, 1) }
+ elseif ($Data.SUMMARY.MHS_av) { [Double]$Data.SUMMARY.MHS_av * [Math]::Pow(1000, 2) }
+ elseif ($Data.SUMMARY.GHS_av) { [Double]$Data.SUMMARY.GHS_av * [Math]::Pow(1000, 3) }
+ elseif ($Data.SUMMARY.THS_av) { [Double]$Data.SUMMARY.THS_av * [Math]::Pow(1000, 4) }
+ elseif ($Data.SUMMARY.PHS_av) { [Double]$Data.SUMMARY.PHS_av * [Math]::Pow(1000, 5) }
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]$Data.SUMMARY.accepted
+ $Shares_Rejected = [Int64]$Data.SUMMARY.rejected
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($this.Algorithm[1]) {
+ Try {
+ $Response = Invoke-TcpRequest -Server "localhost" -Port ($this.Port + 1) -Request $Request -Timeout $Timeout -ErrorAction Stop
+ $Data = $Response.Substring($Response.IndexOf("{"), $Response.LastIndexOf("}") - $Response.IndexOf("{") + 1) -replace " ", "_" | ConvertFrom-Json -ErrorAction Stop
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate_Name = [String]$this.Algorithm[1]
+ $HashRate_Value = If ($Data.SUMMARY.HS_5s) { [Double]$Data.SUMMARY.HS_5s * [Math]::Pow(1000, 0) }
+ elseif ($Data.SUMMARY.KHS_5s) { [Double]$Data.SUMMARY.KHS_5s * [Math]::Pow(1000, 1) }
+ elseif ($Data.SUMMARY.MHS_5s) { [Double]$Data.SUMMARY.MHS_5s * [Math]::Pow(1000, 2) }
+ elseif ($Data.SUMMARY.GHS_5s) { [Double]$Data.SUMMARY.GHS_5s * [Math]::Pow(1000, 3) }
+ elseif ($Data.SUMMARY.THS_5s) { [Double]$Data.SUMMARY.THS_5s * [Math]::Pow(1000, 4) }
+ elseif ($Data.SUMMARY.PHS_5s) { [Double]$Data.SUMMARY.PHS_5s * [Math]::Pow(1000, 5) }
+ elseif ($Data.SUMMARY.KHS_30s) { [Double]$Data.SUMMARY.KHS_30s * [Math]::Pow(1000, 1) }
+ elseif ($Data.SUMMARY.MHS_30s) { [Double]$Data.SUMMARY.MHS_30s * [Math]::Pow(1000, 2) }
+ elseif ($Data.SUMMARY.GHS_30s) { [Double]$Data.SUMMARY.GHS_30s * [Math]::Pow(1000, 3) }
+ elseif ($Data.SUMMARY.THS_30s) { [Double]$Data.SUMMARY.THS_30s * [Math]::Pow(1000, 4) }
+ elseif ($Data.SUMMARY.PHS_30s) { [Double]$Data.SUMMARY.PHS_30s * [Math]::Pow(1000, 5) }
+ elseif ($Data.SUMMARY.HS_av) { [Double]$Data.SUMMARY.HS_av * [Math]::Pow(1000, 0) }
+ elseif ($Data.SUMMARY.KHS_av) { [Double]$Data.SUMMARY.KHS_av * [Math]::Pow(1000, 1) }
+ elseif ($Data.SUMMARY.MHS_av) { [Double]$Data.SUMMARY.MHS_av * [Math]::Pow(1000, 2) }
+ elseif ($Data.SUMMARY.GHS_av) { [Double]$Data.SUMMARY.GHS_av * [Math]::Pow(1000, 3) }
+ elseif ($Data.SUMMARY.THS_av) { [Double]$Data.SUMMARY.THS_av * [Math]::Pow(1000, 4) }
+ elseif ($Data.SUMMARY.PHS_av) { [Double]$Data.SUMMARY.PHS_av * [Math]::Pow(1000, 5) }
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares_Accepted = [Int64]$Data.SUMMARY.accepted
+ $Shares_Rejected = [Int64]$Data.SUMMARY.rejected
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+ }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
+
diff --git a/Includes/MinerAPIs/XmRig.ps1 b/Includes/MinerAPIs/XmRig.ps1
new file mode 100644
index 0000000000..44b7d09108
--- /dev/null
+++ b/Includes/MinerAPIs/XmRig.ps1
@@ -0,0 +1,144 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: XmRig.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class XmRig : Miner {
+ CreateConfigFiles() {
+ $Parameters = $this.Arguments | ConvertFrom-Json -ErrorAction SilentlyContinue
+
+ Try {
+ $ConfigFile = "$(Split-Path $this.Path)\$($Parameters.ConfigFile.FileName)"
+
+ $ThreadsConfig = [PSCustomObject]@{ }
+ $ThreadsConfigFile = "$(Split-Path $this.Path)\$($Parameters.ThreadsConfigFileName)"
+
+ If ($Parameters.ConfigFile.Content.threads) {
+ #Write full config file, ignore possible hw change
+ $Parameters.ConfigFile.Content | ConvertTo-Json -Depth 10 | Out-File -FilePath $ConfigFile -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+ }
+ else {
+ #Check if we have a valid hw file for all installed hardware. If hardware / device order has changed we need to re-create the config files.
+ $ThreadsConfig = Get-Content $ThreadsConfigFile -ErrorAction SilentlyContinue | ConvertFrom-Json -ErrorAction SilentlyContinue
+ If ($ThreadsConfig.Count -lt 1) {
+ If (Test-Path "$(Split-Path $this.Path)\$($this.Algorithm | Select-Object -First 1)-*.json" -PathType Leaf) {
+ #Remove old config files, thread info is no longer valid
+ Write-Message -Level Warn "Hardware change detected. Deleting existing configuration files for miner '$($this.Info)'."
+ Remove-Item "$(Split-Path $this.Path)\ThreadsConfig-$($this.Algorithm | Select-Object -First 1)-*.json" -Force -ErrorAction SilentlyContinue
+ }
+ #Temporarily start miner with pre-config file (without threads config). Miner will then update hw config file with threads info
+ $Parameters.ConfigFile.Content | ConvertTo-Json -Depth 10 | Out-File -FilePath $ThreadsConfigFile -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+ $this.Process = Invoke-CreateProcess -BinaryPath $this.Path -ArgumentList $Parameters.HwDetectArguments -WorkingDirectory (Split-Path $this.Path) -MinerWindowStyle $this.MinerWindowStyle -Priority $this.ProcessPriority -EnvBlock $this.Environment -JobName $this.Info -LogFile $this.LogFile
+
+ If ($this.Process) {
+ $this.ProcessId = [Int32]((Get-CIMInstance CIM_Process | Where-Object { $_.ExecutablePath -eq $this.Path -and $_.CommandLine -like "*$($this.Path)*$($Parameters.HwDetectArguments)*" }).ProcessId)
+ For ($WaitForThreadsConfig = 0; $WaitForThreadsConfig -le 60; $WaitForThreadsConfig++) {
+ If ($ThreadsConfig = @(Get-Content $ThreadsConfigFile -ErrorAction SilentlyContinue | ConvertFrom-Json -ErrorAction SilentlyContinue).threads) {
+ If ($this.DeviceName -like "GPU#*") {
+ ConvertTo-Json -InputObject @($ThreadsConfig | Sort-Object -Property Index -Unique) -Depth 10 | Out-File -FilePath $ThreadsConfigFile -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+ }
+ Else {
+ ConvertTo-Json -InputObject @($ThreadsConfig | Select-Object -Unique) -Depth 10 | Out-File -FilePath $ThreadsConfigFile -Force -Encoding -ErrorAction SilentlyContinue
+ }
+ Break
+ }
+ Start-Sleep -Milliseconds 500
+ }
+ Stop-Process -Id $this.ProcessId -Force -ErrorAction Ignore
+ $this.Process = $null
+ }
+ Else {
+ Write-Message -Level Error "Running temporary miner failed - cannot create threads config files for '$($this.Info)' [Error: '$($Error | Select-Object -First 1)']."
+ Return
+ }
+ }
+
+ If (-not ((Get-Content $ConfigFile -ErrorAction SilentlyContinue | ConvertFrom-Json -ErrorAction SilentlyContinue).threads)) {
+ #Threads config in config file is invalid, retrieve from threads config file
+ $ThreadsConfig = Get-Content $ThreadsConfigFile | ConvertFrom-Json
+ If ($ThreadsConfig.Count -ge 1) {
+ #Write config files. Overwrite because we need to add thread info
+ If ($this.DeviceName -like "GPU#*") {
+ $Parameters.ConfigFile.Content | Add-Member threads ([Array](($ThreadsConfig | Where-Object { $Parameters.Devices -contains $_.index })) * $Parameters.Threads) -Force
+ }
+ Else {
+ #CPU thread config does not contain index information
+ $Parameters.ConfigFile.Content | Add-Member threads ([Array]($ThreadsConfig * $Parameters.Threads)) -Force
+ }
+ $Parameters.ConfigFile.Content | ConvertTo-Json -Depth 10 | Out-File -FilePath $ConfigFile -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+ }
+ Else {
+ Write-Message -Level Error "Error parsing threads config file - cannot create miner config files for '$($this.Info)' [Error: '$($Error | Select-Object -First 1)']."
+ Return
+ }
+ }
+ }
+ }
+ Catch {
+ Write-Message -Level Error "Creating miner config files for '$($this.Info)' failed [Error: '$($Error | Select-Object -First 1)']."
+ Return
+ }
+ }
+
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = "http://localhost:$($this.Port)/api.json"
+
+ Try {
+ $Data = Invoke-RestMethod -Uri $Request -TimeoutSec $Timeout
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = [String]$this.Algorithm[0]
+ $HashRate_Value = [Double]$Data.hashrate.total[0]
+ If (-not $HashRate_Value) { $HashRate_Value = [Double]$Data.hashrate.total[1] } #fix
+ If (-not $HashRate_Value) { $HashRate_Value = [Double]$Data.hashrate.total[2] } #fix
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]$Data.results.shares_good
+ $Shares_Rejected = [Int64]($Data.results.shares_total - $Data.results.shares_good)
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
diff --git a/Includes/MinerAPIs/lolMiner.ps1 b/Includes/MinerAPIs/lolMiner.ps1
new file mode 100644
index 0000000000..3c1a9aea16
--- /dev/null
+++ b/Includes/MinerAPIs/lolMiner.ps1
@@ -0,0 +1,100 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: lolMiner.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+class lolMiner : Miner {
+ [Object]GetMinerData () {
+ $Timeout = 5 #seconds
+ $Data = [PSCustomObject]@{ }
+ $PowerUsage = [Double]0
+ $Sample = [PSCustomObject]@{ }
+
+ $Request = "http://localhost:$($this.Port)/summary"
+
+ Try {
+ $Data = Invoke-RestMethod -Uri $Request -TimeoutSec $Timeout
+ }
+ Catch {
+ Return $null
+ }
+
+ $HashRate = [PSCustomObject]@{ }
+ $HashRate_Name = [String]$this.Algorithm[0]
+ $HashRate_Unit = [Int64]1
+ Switch ($Data.Algorithms[0].Performance_Unit) {
+ "kh/s" { $HashRate_Unit = [Math]::Pow(10,3) }
+ "Mh/s" { $HashRate_Unit = [Math]::Pow(10,6) }
+ "GH/s" { $HashRate_Unit = [Math]::Pow(10,9) }
+ "TH/s" { $HashRate_Unit = [Math]::Pow(10,12) }
+ "PH/s" { $HashRate_Unit = [Math]::Pow(10,15) }
+ "EH/s" { $HashRate_Unit = [Math]::Pow(10,18) }
+ "ZH/s" { $HashRate_Unit = [Math]::Pow(10,21) }
+ "YH/s" { $HashRate_Unit = [Math]::Pow(10,24) }
+ Default { $HashRate_Unit = 1 }
+ }
+ $HashRate_Value = [Double]($Data.Algorithms[0].Total_Performance * $HashRate_Unit)
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares = [PSCustomObject]@{ }
+ $Shares_Accepted = [Int64]$Data.Algorithms[0].Total_Accepted
+ $Shares_Rejected = [Int64]$Data.Algorithms[0].Total_Rejected
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+
+ If ($this.Algorithm[1]) {
+ $HashRate_Name = [String]$this.Algorithm[1]
+ $HashRate_Unit = [Int64]1
+ Switch ($Data.Algorithms[1].Performance_Unit) {
+ "kh/s" { $HashRate_Unit = [Math]::Pow(10,3) }
+ "Mh/s" { $HashRate_Unit = [Math]::Pow(10,6) }
+ "GH/s" { $HashRate_Unit = [Math]::Pow(10,9) }
+ "TH/s" { $HashRate_Unit = [Math]::Pow(10,12) }
+ "PH/s" { $HashRate_Unit = [Math]::Pow(10,15) }
+ "EH/s" { $HashRate_Unit = [Math]::Pow(10,18) }
+ "ZH/s" { $HashRate_Unit = [Math]::Pow(10,21) }
+ "YH/s" { $HashRate_Unit = [Math]::Pow(10,24) }
+ Default { $HashRate_Unit = 1 }
+ }
+ $HashRate_Value = [Double]($Data.Algorithms[1].Total_Performance * $HashRate_Unit)
+ $HashRate | Add-Member @{ $HashRate_Name = [Double]$HashRate_Value }
+
+ $Shares_Accepted = [Int64]$Data.Algorithms[1].Total_Accepted
+ $Shares_Rejected = [Int64]$Data.Algorithms[1].Total_Rejected
+ $Shares | Add-Member @{ $HashRate_Name = @($Shares_Accepted, $Shares_Rejected, ($Shares_Accepted + $Shares_Rejected)) }
+ }
+
+ If ($this.ReadPowerUsage) {
+ $PowerUsage = $this.GetPowerUsage()
+ }
+
+ If ($HashRate.PSObject.Properties.Value -gt 0) {
+ $Sample = [PSCustomObject]@{
+ Date = (Get-Date).ToUniversalTime()
+ HashRate = $HashRate
+ PowerUsage = $PowerUsage
+ Shares = $Shares
+ }
+ Return $Sample
+ }
+ Return $null
+ }
+}
diff --git a/Includes/OpenCL/Cl.cs b/Includes/OpenCL/Cl.cs
new file mode 100644
index 0000000000..c532dcc62d
--- /dev/null
+++ b/Includes/OpenCL/Cl.cs
@@ -0,0 +1,380 @@
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace OpenCl
+{
+ [Flags]
+ public enum FpConfig : ulong
+ {
+ FpDenorm = (1 << 0),
+ FpInfNan = (1 << 1),
+ FpRoundToNearest = (1 << 2),
+ FpRoundToZero = (1 << 3),
+ FpRoundToInf = (1 << 4),
+ FpFma = (1 << 5),
+ FpSoftFloat = (1 << 6),
+ FpCorrectlyRoundedDivideSqrt = (1 << 7),
+ }
+
+ public enum ProfilingInfo: int
+ {
+ Queued = 0x1280,
+ Submit = 0x1281,
+ Start = 0x1282,
+ End = 0x1283,
+ }
+
+ public enum SamplerInfo : uint
+ {
+ ReferenceCount = 0x1150,
+ Context = 0x1151,
+ NormalizedCoords = 0x1152,
+ AddressingMode = 0x1153,
+ FilterMode = 0x1154,
+ }
+
+ public enum FilterMode : uint
+ {
+ Nearest = 0x1140,
+ Linear = 0x1141,
+ }
+
+ public enum AddressingMode : uint
+ {
+ None = 0x1130,
+ ClampToEdge = 0x1131,
+ Clamp = 0x1132,
+ Repeat = 0x1133,
+ }
+
+ public enum EventInfo: int
+ {
+ CommandQueue = 0x11D0,
+ CommandType = 0x11D1,
+ ReferenceCount = 0x11D2,
+ CommandExecutionStatus = 0x11D3,
+ }
+
+ [Flags]
+ public enum MapFlags: int
+ {
+ Read = (1 << 0),
+ Write = (1 << 1),
+ }
+
+ public enum KernelWorkGroupInfo : int // cl_int
+ {
+ WorkGroupSize = 0x11B0,
+ CompileWorkGroupSize = 0x11B1,
+ LocalMemSize = 0x11B2
+ }
+
+ public enum KernelInfo : int // cl_int
+ {
+ FunctionName = 0x1190,
+ NumArgs = 0x1191,
+ ReferenceCount = 0x1192,
+ Context = 0x1193,
+ Program = 0x1194
+ }
+
+ public enum CommandQueueInfo : int // cl_int
+ {
+ Context = 0x1090,
+ Device = 0x1091,
+ ReferenceCount = 0x1092,
+ Properties = 0x1093
+ }
+
+ public enum ImageInfo : uint // cl_uint
+ {
+ Format = 0x1110,
+ ElementSize = 0x1111,
+ RowPitch = 0x1112,
+ SlicePitch = 0x1113,
+ Width = 0x1114,
+ Height = 0x1115,
+ Depth = 0x1116,
+ }
+
+ public enum MemInfo : uint // cl_uint
+ {
+ Type = 0x1100,
+ Flags = 0x1101,
+ Size = 0x1102,
+ HostPtr = 0x1103,
+ MapCount = 0x1104,
+ ReferenceCount = 0x1105,
+ Context = 0x1106,
+ }
+
+ public enum ContextInfo : uint // cl_uint
+ {
+ ReferenceCount = 0x1080,
+ Devices = 0x1081,
+ Properties = 0x1082,
+ }
+
+ public enum ChannelType : uint
+ {
+ SnormInt8 = 0x10D0,
+ SnormInt16 = 0x10D1,
+ UnormInt8 = 0x10D2,
+ UnormInt16 = 0x10D3,
+ UnormShort565 = 0x10D4,
+ UnormShort555 = 0x10D5,
+ UnormInt101010 = 0x10D6,
+ SignedInt8 = 0x10D7,
+ SignedInt16 = 0x10D8,
+ SignedInt32 = 0x10D9,
+ UnsignedInt8 = 0x10DA,
+ UnsignedInt16 = 0x10DB,
+ UnsignedInt32 = 0x10DC,
+ HalfFloat = 0x10DD,
+ Float = 0x10DE,
+ }
+
+ public enum ChannelOrder : uint
+ {
+ R = 0x10B0,
+ A = 0x10B1,
+ RG = 0x10B2,
+ RA = 0x10B3,
+ RGB = 0x10B4,
+ RGBA = 0x10B5,
+ BGRA = 0x10B6,
+ ARGB = 0x10B7,
+ Intensity = 0x10B8,
+ Luminance = 0x10B9,
+ }
+
+ [Flags]
+ public enum DeviceExecCapabilities : ulong
+ {
+ ExecKernel = (1 << 0),
+ ExecNativeKernel = (1 << 1),
+ }
+
+ [Flags]
+ public enum DeviceType : ulong
+ {
+ Default = (1 << 0),
+ Cpu = (1 << 1),
+ Gpu = (1 << 2),
+ Accelerator = (1 << 3),
+ All = 0xFFFFFFFF,
+ }
+
+ public enum DeviceMemCacheType : uint
+ {
+ None = 0x0,
+ ReadOnlyCache = 0x1,
+ ReadWriteCache = 0x2,
+ }
+
+ public enum DeviceLocalMemType : uint
+ {
+ Local = 0x1,
+ Global = 0x2,
+ }
+
+ public enum ErrorCode : int
+ {
+ Success = 0,
+
+ DeviceNotFound = -1,
+ DeviceNotAvailable = -2,
+ CompilerNotAvailable = -3,
+ MemObjectAllocationFailure = -4,
+ OutOfResources = -5,
+ OutOfHostMemory = -6,
+ ProfilingInfoNotAvailable = -7,
+ MemCopyOverlap = -8,
+ ImageFormatMismatch = -9,
+ ImageFormatNotSupported = -10,
+ BuildProgramFailure = -11,
+ MapFailure = -12,
+
+ InvalidValue = -30,
+ InvalidDeviceType = -31,
+ InvalidPlatform = -32,
+ InvalidDevice = -33,
+ InvalidContext = -34,
+ InvalidQueueProperties = -35,
+ InvalidCommandQueue = -36,
+ InvalidHostPtr = -37,
+ InvalidMemObject = -38,
+ InvalidImageFormatDescriptor = -39,
+ InvalidImageSize = -40,
+ InvalidSampler = -41,
+ InvalidBinary = -42,
+ InvalidBuildOptions = -43,
+ InvalidProgram = -44,
+ InvalidProgramExecutable = -45,
+ InvalidKernelName = -46,
+ InvalidKernelDefinition = -47,
+ InvalidKernel = -48,
+ InvalidArgIndex = -49,
+ InvalidArgValue = -50,
+ InvalidArgSize = -51,
+ InvalidKernelArgs = -52,
+ InvalidWorkDimension = -53,
+ InvalidWorkGroupSize = -54,
+ InvalidWorkItemSize = -55,
+ InvalidGlobalOffset = -56,
+ InvalidEventWaitList = -57,
+ InvalidEvent = -58,
+ InvalidOperation = -59,
+ InvalidGlObject = -60,
+ InvalidBufferSize = -61,
+ InvalidMipLevel = -62,
+ }
+
+ internal delegate ErrorCode GetInfoDelegate(IntPtr handle, uint paramName, IntPtr paramValueSize, IntPtr paramValue, out IntPtr paramValueSizeRet);
+
+ internal delegate ErrorCode GetBuildInfoDelegate(IntPtr program, IntPtr device, uint paramName, IntPtr paramValueSize, IntPtr paramValue, out IntPtr paramValueSizeRet);
+
+ internal static class Cl
+ {
+ internal static T GetInfo(GetInfoDelegate method, IntPtr handle, uint name) where T : struct
+ {
+ IntPtr size;
+ object result = default(T);
+ var h = GCHandle.Alloc(result, GCHandleType.Pinned);
+ try {
+ ErrorCode error = method(handle, name, (IntPtr)Marshal.SizeOf(), h.AddrOfPinnedObject(), out size);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ }
+ finally {
+ h.Free();
+ }
+ return (T)result;
+ }
+
+ internal static string GetInfoString(GetInfoDelegate method, IntPtr handle, uint name)
+ {
+ IntPtr size;
+ ErrorCode error = method(handle, name, IntPtr.Zero, IntPtr.Zero, out size);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ string result = null;
+ IntPtr buf = Marshal.AllocHGlobal(size);
+ try {
+ error = method(handle, name, size, buf, out size);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ result = Marshal.PtrToStringAnsi(buf);
+ }
+ finally {
+ Marshal.FreeHGlobal(buf);
+ }
+ return result;
+ }
+
+ internal static T GetInfoEnum(GetInfoDelegate method, IntPtr handle, uint name) where T : struct
+ {
+ var type = Enum.GetUnderlyingType(typeof(T));
+ var result = Activator.CreateInstance(type);
+ var size = (IntPtr)Marshal.SizeOf(type);
+ var h = GCHandle.Alloc(result, GCHandleType.Pinned);
+ try {
+ ErrorCode error = method(handle, name, size, h.AddrOfPinnedObject(), out size);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ }
+ finally {
+ h.Free();
+ }
+ return (T)result;
+ }
+
+ internal static T[] GetInfoArray(GetInfoDelegate method, IntPtr handle, uint name) where T : struct
+ {
+ var elemSize = Marshal.SizeOf();
+ IntPtr arraySize;
+ ErrorCode error = method(handle, name, IntPtr.Zero, IntPtr.Zero, out arraySize);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ int count = (int)arraySize/elemSize;
+ if (count*elemSize < (int)arraySize) {
+ throw new InvalidOperationException(String.Format("Array size is incompatible with managed element size: array size = {0}, sizeof({1}) = {2})", arraySize, typeof(T), elemSize));
+ }
+ T[] result = new T[count];
+ GCHandle gch = GCHandle.Alloc(result, GCHandleType.Pinned);
+ try {
+ error = method(handle, name, (IntPtr)(count*elemSize), gch.AddrOfPinnedObject(), out arraySize);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ }
+ finally {
+ gch.Free();
+ }
+ return result;
+ }
+
+ internal static T GetBuildInfo(GetBuildInfoDelegate method, IntPtr program, IntPtr device, uint name) where T : struct
+ {
+ IntPtr size;
+ T result = default(T);
+ var h = GCHandle.Alloc(result, GCHandleType.Pinned);
+ try {
+ ErrorCode error = method(program, device, name, (IntPtr)Marshal.SizeOf(), h.AddrOfPinnedObject(), out size);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ }
+ finally {
+ h.Free();
+ }
+ return result;
+ }
+
+ internal static string GetBuildInfoString(GetBuildInfoDelegate method, IntPtr program, IntPtr device, uint name)
+ {
+ IntPtr size;
+ ErrorCode error = method(program, device, name, IntPtr.Zero, IntPtr.Zero, out size);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ string result = null;
+ IntPtr buf = Marshal.AllocHGlobal(size);
+ try {
+ error = method(program, device, name, size, buf, out size);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ result = Marshal.PtrToStringAnsi(buf);
+ }
+ finally {
+ Marshal.FreeHGlobal(buf);
+ }
+ return result;
+ }
+
+ internal static T GetBuildInfoEnum(GetBuildInfoDelegate method, IntPtr program, IntPtr device, uint name) where T : struct
+ {
+ var type = Enum.GetUnderlyingType(typeof(T));
+ var result = Activator.CreateInstance(type);
+ var size = (IntPtr)Marshal.SizeOf(type);
+ var h = GCHandle.Alloc(result, GCHandleType.Pinned);
+ try {
+ ErrorCode error = method(program, device, name, size, h.AddrOfPinnedObject(), out size);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ }
+ finally {
+ h.Free();
+ }
+ return (T)result;
+ }
+ }
+}
diff --git a/Includes/OpenCL/CommandQueue.cs b/Includes/OpenCL/CommandQueue.cs
new file mode 100644
index 0000000000..b196ba1c83
--- /dev/null
+++ b/Includes/OpenCL/CommandQueue.cs
@@ -0,0 +1,334 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace OpenCl
+{
+ [Flags]
+ public enum CommandQueueProperties : ulong
+ {
+ None = 0,
+ OutOfOrderExecModeEnable = (1 << 0),
+ ProfilingEnable = (1 << 1),
+ }
+
+ public sealed class CommandQueue : RefCountedObject
+ {
+ internal CommandQueue(IntPtr handle) : base(handle) { }
+
+ private const uint CL_QUEUE_CONTEXT = 0x1090;
+ private const uint CL_QUEUE_DEVICE = 0x1091;
+ private const uint CL_QUEUE_REFERENCE_COUNT = 0x1092;
+ private const uint CL_QUEUE_PROPERTIES = 0x1093;
+ private const uint CL_QUEUE_SIZE = 0x1094;
+ private const uint CL_QUEUE_DEVICE_DEFAULT = 0x1095;
+
+ // CommandQueue attributes
+
+ public Context Context
+ {
+ get {
+ var ctx = Cl.GetInfo(NativeMethods.clGetCommandQueueInfo, this.handle, CL_QUEUE_CONTEXT);
+ return new Context(ctx);
+ }
+ }
+
+ public Device Device
+ {
+ get {
+ var dev = Cl.GetInfo(NativeMethods.clGetCommandQueueInfo, this.handle, CL_QUEUE_DEVICE);
+ return new Device(dev);
+ }
+ }
+
+ public uint ReferenceCount
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetCommandQueueInfo, this.handle, CL_QUEUE_REFERENCE_COUNT); }
+ }
+
+ public CommandQueueProperties Properties
+ {
+ get { return Cl.GetInfoEnum(NativeMethods.clGetCommandQueueInfo, this.handle, CL_QUEUE_PROPERTIES); }
+ }
+
+ public uint Size
+ {
+ get { return (uint)Cl.GetInfo(NativeMethods.clGetCommandQueueInfo, this.handle, CL_QUEUE_SIZE); }
+ }
+
+ public CommandQueue DeviceDefault
+ {
+ get {
+ var queue = Cl.GetInfo(NativeMethods.clGetCommandQueueInfo, this.handle, CL_QUEUE_DEVICE_DEFAULT);
+ return new CommandQueue(queue);
+ }
+ }
+
+ // CommandQueue methods
+
+ public Event EnqueueReadBuffer(Mem buffer, bool blockingRead, T[] ptr) where T: struct
+ {
+ return EnqueueReadBuffer(buffer, blockingRead, ptr, null);
+ }
+
+ public Event EnqueueReadBuffer(Mem buffer, bool blockingRead, T[] ptr, Event[] eventWaitList) where T: struct
+ {
+ var offset = 0;
+ var length = buffer.Size;
+ if (length > (uint)(Marshal.SizeOf()*ptr.Length)) {
+ throw new ArgumentException(String.Format("Data array is to small: expected length >= {0}, found {1}.", length, Marshal.SizeOf()*ptr.Length));
+ }
+ var numEvents = 0;
+ IntPtr[] events = null;
+ if (eventWaitList != null) {
+ numEvents = eventWaitList.Length;
+ events = Event.ToIntPtr(eventWaitList);
+ }
+ IntPtr result = IntPtr.Zero;
+ GCHandle gch = GCHandle.Alloc(ptr, GCHandleType.Pinned);
+ try {
+ var error = NativeMethods.clEnqueueReadBuffer(
+ this.handle,
+ buffer.handle,
+ blockingRead ? 1u : 0u,
+ (IntPtr)offset,
+// (IntPtr)(Marshal.SizeOf()*ptr.Length),
+ (IntPtr)length,
+ gch.AddrOfPinnedObject(),
+ (uint)numEvents,
+ events,
+ out result);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ }
+ finally {
+ gch.Free();
+ }
+ return new Event(result);
+ }
+
+ public Event EnqueueReadBuffer(Mem buffer, bool blockingRead, uint offset, uint length, T[] ptr, Event[] eventWaitList) where T: struct
+ {
+ var numEvents = 0;
+ IntPtr[] events = null;
+ if (eventWaitList != null) {
+ numEvents = eventWaitList.Length;
+ events = Event.ToIntPtr(eventWaitList);
+ }
+ IntPtr result = IntPtr.Zero;
+ GCHandle gch = GCHandle.Alloc(ptr, GCHandleType.Pinned);
+ try {
+ var error = NativeMethods.clEnqueueReadBuffer(
+ this.handle,
+ buffer.handle,
+ blockingRead ? 1u : 0u,
+ (IntPtr)offset,
+ (IntPtr)length,
+ gch.AddrOfPinnedObject(),
+ (uint)numEvents,
+ events,
+ out result);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ }
+ finally {
+ gch.Free();
+ }
+ return new Event(result);
+ }
+
+ public Event EnqueueWriteBuffer(Mem buffer, bool blockingWrite, T[] ptr) where T: struct
+ {
+ return EnqueueWriteBuffer(buffer, blockingWrite, ptr, null);
+ }
+
+ public Event EnqueueWriteBuffer(Mem buffer, bool blockingWrite, T[] ptr, Event[] eventWaitList) where T: struct
+ {
+ var offset = 0;
+ var length = (uint)(Marshal.SizeOf()*ptr.Length);
+ if (buffer.Size < length) {
+ throw new ArgumentException(String.Format("Memory buffer is to small: expected length >= {0}, found {1}.", length, buffer.Size));
+ }
+ var numEvents = 0;
+ IntPtr[] events = null;
+ if (eventWaitList != null) {
+ numEvents = eventWaitList.Length;
+ events = Event.ToIntPtr(eventWaitList);
+ }
+ IntPtr result = IntPtr.Zero;
+ GCHandle gch = GCHandle.Alloc(ptr, GCHandleType.Pinned);
+ try {
+ var error = NativeMethods.clEnqueueWriteBuffer(
+ this.handle,
+ buffer.handle,
+ blockingWrite ? 1u : 0u,
+ (IntPtr)offset,
+ (IntPtr)length,
+ gch.AddrOfPinnedObject(),
+ (uint)numEvents,
+ events,
+ out result);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ }
+ finally {
+ gch.Free();
+ }
+ return new Event(result);
+ }
+
+ public Event EnqueueWriteBuffer(Mem buffer, bool blockingRead, uint offset, uint length, T[] ptr, Event[] eventWaitList) where T: struct
+ {
+ var numEvents = 0;
+ IntPtr[] events = null;
+ if (eventWaitList != null) {
+ numEvents = eventWaitList.Length;
+ events = Event.ToIntPtr(eventWaitList);
+ }
+ IntPtr result = IntPtr.Zero;
+ GCHandle gch = GCHandle.Alloc(ptr, GCHandleType.Pinned);
+ try {
+ var error = NativeMethods.clEnqueueWriteBuffer(
+ this.handle,
+ buffer.handle,
+ blockingRead ? 1u : 0u,
+ (IntPtr)offset,
+ (IntPtr)length,
+ gch.AddrOfPinnedObject(),
+ (uint)numEvents,
+ events,
+ out result);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ }
+ finally {
+ gch.Free();
+ }
+ return new Event(result);
+ }
+
+ public Event EnqueueFillBuffer(Mem buffer, T pattern) where T: struct
+ {
+ return EnqueueFillBuffer(buffer, pattern, null);
+ }
+
+ public Event EnqueueFillBuffer(Mem buffer, T pattern, Event[] eventWaitList) where T: struct
+ {
+ return EnqueueFillBuffer(buffer, new T[] { pattern }, 0, buffer.Size, eventWaitList);
+ }
+
+ public Event EnqueueFillBuffer(Mem buffer, T[] pattern, uint offset, uint length, Event[] eventWaitList) where T: struct
+ {
+ var numEvents = 0;
+ IntPtr[] events = null;
+ if (eventWaitList != null) {
+ numEvents = eventWaitList.Length;
+ events = Event.ToIntPtr(eventWaitList);
+ }
+ IntPtr result = IntPtr.Zero;
+ GCHandle gch = GCHandle.Alloc(pattern, GCHandleType.Pinned);
+ try {
+ var error = NativeMethods.clEnqueueFillBuffer(
+ this.handle,
+ buffer.handle,
+ gch.AddrOfPinnedObject(),
+ (IntPtr)(Marshal.SizeOf()*pattern.Length),
+ (IntPtr)offset,
+ (IntPtr)length,
+ (uint)numEvents,
+ events,
+ out result);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ }
+ finally {
+ gch.Free();
+ }
+ return new Event(result);
+ }
+
+ public Event EnqueueNDRangeKernel(Kernel kernel, uint[] globalWorkOffset, uint[] globalWorkSize, uint[] localWorkSize, Event[] eventWaitList)
+ {
+ var workDim = globalWorkSize.Length;
+ if (globalWorkOffset != null && globalWorkOffset.Length != workDim) {
+ throw new ArgumentException(String.Format("Invalid length of globalWorkOffset array: expected {0}, found {1}.", workDim, globalWorkOffset.Length));
+ }
+ if (localWorkSize != null && localWorkSize.Length != workDim) {
+ throw new ArgumentException(String.Format("Invalid length of localWorkSize array: expected {0}, found {1}.", workDim, localWorkSize.Length));
+ }
+ var numEvents = 0;
+ IntPtr[] events = null;
+ if (eventWaitList != null) {
+ numEvents = eventWaitList.Length;
+ events = Event.ToIntPtr(eventWaitList);
+ }
+ IntPtr result;
+ var error = NativeMethods.clEnqueueNDRangeKernel(this.handle, kernel.handle, (uint)workDim, globalWorkOffset, globalWorkSize, localWorkSize, (uint)numEvents, events, out result);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ return new Event(result);
+ }
+
+ public Event EnqueueNDRangeKernel(Kernel kernel, int[] globalWorkOffset, int[] globalWorkSize, int[] localWorkSize, Event[] eventWaitList)
+ {
+ var workDim = globalWorkSize.Length;
+ if (globalWorkOffset != null && globalWorkOffset.Length != workDim) {
+ throw new ArgumentException(String.Format("Invalid length of globalWorkOffset array: expected {0}, found {1}.", workDim, globalWorkOffset.Length));
+ }
+ if (localWorkSize != null && localWorkSize.Length != workDim) {
+ throw new ArgumentException(String.Format("Invalid length of localWorkSize array: expected {0}, found {1}.", workDim, localWorkSize.Length));
+ }
+ var numEvents = 0;
+ IntPtr[] events = null;
+ if (eventWaitList != null) {
+ numEvents = eventWaitList.Length;
+ events = Event.ToIntPtr(eventWaitList);
+ }
+ IntPtr result;
+ var error = NativeMethods.clEnqueueNDRangeKernel(this.handle, kernel.handle, workDim, globalWorkOffset, globalWorkSize, localWorkSize, numEvents, events, out result);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ return new Event(result);
+ }
+
+ public void Finish()
+ {
+ NativeMethods.clFinish(this.handle);
+ }
+
+ // RefCountedObject
+
+ protected override void Retain()
+ {
+ NativeMethods.clRetainCommandQueue(this.handle);
+ }
+
+ protected override void Release()
+ {
+ NativeMethods.clReleaseCommandQueue(this.handle);
+ }
+
+ // static factory methods
+
+ public static CommandQueue CreateCommandQueue(Context context, Device device)
+ {
+ return CreateCommandQueue(context, device, CommandQueueProperties.None);
+ }
+
+ public static CommandQueue CreateCommandQueue(Context context, Device device, CommandQueueProperties properties)
+ {
+ ErrorCode error;
+ var res = NativeMethods.clCreateCommandQueue(context.handle, device.handle, properties, out error);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ return new CommandQueue(res);
+ }
+ }
+}
diff --git a/Includes/OpenCL/Context.cs b/Includes/OpenCL/Context.cs
new file mode 100644
index 0000000000..f6774b4aa2
--- /dev/null
+++ b/Includes/OpenCL/Context.cs
@@ -0,0 +1,225 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace OpenCl
+{
+ public delegate void ContextNotify(string errInfo, object userData);
+
+ internal delegate void ContextNotifyInternal(IntPtr errInfo, IntPtr privateData, IntPtr cb, IntPtr userData);
+
+ internal class ContextNotifyData : IDisposable
+ {
+ private ContextNotify callback;
+ private object data;
+
+ private GCHandle handle;
+
+ public ContextNotifyData(ContextNotify callback, object data)
+ {
+ this.callback = callback;
+ this.data = data;
+ this.handle = GCHandle.Alloc(this, GCHandleType.Normal);
+ }
+
+ ~ContextNotifyData()
+ {
+ Dispose(false);
+ }
+
+ public static void Callback(IntPtr errInfo, IntPtr privateData, IntPtr cb, IntPtr userData)
+ {
+ var h = GCHandle.FromIntPtr(userData);
+ var d = h.Target as ContextNotifyData;
+ d.callback(Marshal.PtrToStringAnsi(errInfo), d.data);
+ }
+
+ public IntPtr Handle
+ {
+ get { return GCHandle.ToIntPtr(this.handle); }
+ }
+
+ // IDisposable
+
+ private bool disposed = false;
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposed) {
+ this.handle.Free();
+ disposed = true;
+ }
+ }
+ }
+
+ public enum ContextProperties : uint
+ {
+ Platform = 0x1084,
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct ContextProperty
+ {
+ public static readonly ContextProperty Zero = new ContextProperty(0);
+
+ private readonly uint name;
+ private readonly IntPtr value;
+
+ public ContextProperty(ContextProperties property, IntPtr value)
+ {
+ this.name = (uint)property;
+ this.value = value;
+ }
+
+ public ContextProperty(ContextProperties property)
+ {
+ this.name = (uint)property;
+ this.value = IntPtr.Zero;
+ }
+
+ public ContextProperties Name
+ {
+ get { return (ContextProperties)this.name; }
+ }
+
+ public IntPtr Value
+ {
+ get { return this.value; }
+ }
+ }
+
+ public sealed class Context : RefCountedObject
+ {
+// public static readonly Context Zero = new Context(IntPtr.Zero, default(GCHandle));
+
+ private const uint CL_CONTEXT_REFERENCE_COUNT = 0x1080;
+ private const uint CL_CONTEXT_DEVICES = 0x1081;
+ private const uint CL_CONTEXT_PROPERTIES = 0x1082;
+ private const uint CL_CONTEXT_NUM_DEVICES = 0x1083;
+
+ private ContextNotifyData callback;
+
+ internal Context(IntPtr handle) : this(handle, null) { }
+
+ internal Context(IntPtr handle, ContextNotifyData cb) : base(handle)
+ {
+ this.callback = cb;
+ }
+
+ // Context attributes
+
+ public uint ReferenceCount
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetContextInfo, this.handle, CL_CONTEXT_REFERENCE_COUNT); }
+ }
+
+ public Device[] Devices
+ {
+ get { return Device.FromIntPtr(Cl.GetInfoArray(NativeMethods.clGetContextInfo, this.handle, CL_CONTEXT_DEVICES)); }
+ }
+
+ public ContextProperty[] Properties
+ {
+ get { return Cl.GetInfoArray(NativeMethods.clGetContextInfo, this.handle, CL_CONTEXT_PROPERTIES); }
+ }
+
+ // RefCountedHandle
+
+ protected override void Retain()
+ {
+ NativeMethods.clRetainContext(this.handle);
+ }
+
+ protected override void Release()
+ {
+ NativeMethods.clReleaseContext(this.handle);
+ }
+
+ // IDisposable
+
+ private bool disposed = false;
+
+ protected override void Dispose(bool disposing)
+ {
+ if (!disposed) {
+ if (disposing && this.callback != null) {
+ this.callback.Dispose();
+ }
+ this.callback = null;
+ this.disposed = true;
+ }
+ base.Dispose(disposing);
+ }
+
+ // static factory methods
+
+ public static Context CreateContext(Platform platform, Device device, ContextNotify callback, object userData)
+ {
+ var pty = platform != null ? new ContextProperty[] { new ContextProperty(ContextProperties.Platform, platform.handle), ContextProperty.Zero } : null;
+ var dev = new IntPtr[] { device.handle };
+ var pfn = (ContextNotifyData)null;
+ var pcb = (ContextNotifyInternal)null;
+ var ptr = IntPtr.Zero;
+ if (callback != null) {
+ pfn = new ContextNotifyData(callback, userData);
+ pcb = ContextNotifyData.Callback;
+ ptr = pfn.Handle;
+ }
+ var err = ErrorCode.Success;
+ var ctx = NativeMethods.clCreateContext(pty, 1, dev, pcb, ptr, out err);
+ if (err != ErrorCode.Success) {
+ throw new OpenClException(err);
+ }
+ return new Context(ctx, pfn);
+ }
+
+ public static Context CreateContext(Platform platform, Device[] devices, ContextNotify callback, object userData)
+ {
+ var pty = platform != null ? new ContextProperty[] { new ContextProperty(ContextProperties.Platform, platform.handle), ContextProperty.Zero } : null;
+ var num = devices.Length;
+ var dev = new IntPtr[num];
+ for (var i=0; i(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_TOPOLOGY_AMD);
+
+ if (PCIBus_AMD != null && PCIBus_AMD.Length == 24 && PCIBus_AMD[0] == 1) {
+ return PCIBus_AMD[21];
+ }
+ }
+ catch (OpenClException) {
+ }
+
+ try {
+ int PCIBus_NV = Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_PCI_BUS_ID_NV);
+
+ return PCIBus_NV;
+ }
+ catch (OpenClException) {
+ }
+
+ return -1;
+ }
+ }
+
+ public uint AddressBits
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_ADDRESS_BITS); }
+ }
+
+ public bool Available
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_AVAILABLE) != 0; }
+ }
+
+ public bool CompilerAvailable
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_COMPILER_AVAILABLE) != 0; }
+ }
+
+ public FpConfig DoubleFpConfig
+ {
+ get { return Cl.GetInfoEnum(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_DOUBLE_FP_CONFIG); }
+ }
+
+ public bool EndianLittle
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_ENDIAN_LITTLE) != 0; }
+ }
+
+ public bool ErrorCorrectionSupport
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_ERROR_CORRECTION_SUPPORT) != 0; }
+ }
+
+ public DeviceExecCapabilities ExecCapabilities
+ {
+ get { return Cl.GetInfoEnum(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_EXECUTION_CAPABILITIES); }
+ }
+
+ public string[] Extensions
+ {
+ get {
+ var res = Cl.GetInfoString(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_EXTENSIONS);
+ return res.Split(new char[] { ' ' });
+ }
+ }
+
+ public ulong GlobalMemCacheSize
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE); }
+ }
+
+ public DeviceMemCacheType GlobalMemCacheType
+ {
+ get { return Cl.GetInfoEnum(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE); }
+ }
+
+ public uint GlobalMemCachelineSize
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE); }
+ }
+
+ public ulong GlobalMemSize
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_GLOBAL_MEM_SIZE); }
+ }
+
+// public FpConfig HalfFpConfig
+// {
+// get { return Cl.GetInfoEnum(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_HALF_FP_CONFIG); }
+// }
+
+ public bool ImageSupport
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_IMAGE_SUPPORT) != 0; }
+ }
+
+// CL_DEVICE_IMAGE2D_MAX_HEIGHT
+// Return type: size_t
+//
+// Max height of 2D image in pixels. The minimum value is 8192 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.
+//
+// CL_DEVICE_IMAGE2D_MAX_WIDTH
+// Return type: size_t
+//
+// Max width of 2D image in pixels. The minimum value is 8192 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.
+//
+// CL_DEVICE_IMAGE3D_MAX_DEPTH
+// Return type: size_t
+//
+// Max depth of 3D image in pixels. The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.
+//
+// CL_DEVICE_IMAGE3D_MAX_HEIGHT
+// Return type: size_t
+//
+// Max height of 3D image in pixels. The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.
+//
+// CL_DEVICE_IMAGE3D_MAX_WIDTH
+// Return type: size_t
+//
+// Max width of 3D image in pixels. The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.
+
+ public ulong LocalMemSize
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_LOCAL_MEM_SIZE); }
+ }
+
+ public DeviceLocalMemType LocalMemType
+ {
+ get { return Cl.GetInfoEnum(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_LOCAL_MEM_TYPE); }
+ }
+
+ public uint MaxClockFrequency
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_MAX_CLOCK_FREQUENCY); }
+ }
+
+ public uint MaxComputeUnits
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_MAX_COMPUTE_UNITS); }
+ }
+
+ public uint MaxConstantArgs
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_MAX_CONSTANT_ARGS); }
+ }
+
+ public uint MaxConstantBufferSize
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE); }
+ }
+
+ public ulong MaxMemAllocSize
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_MAX_MEM_ALLOC_SIZE); }
+ }
+
+ public uint MaxParameterSize
+ {
+ get { return (uint)Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_MAX_PARAMETER_SIZE); }
+ }
+
+ public uint MaxReadImageArgs
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_MAX_READ_IMAGE_ARGS); }
+ }
+
+ public uint MaxSamplers
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_MAX_SAMPLERS); }
+ }
+
+ public uint MaxWorkGroupSize
+ {
+ get { return (uint)Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_MAX_WORK_GROUP_SIZE); }
+ }
+
+ public uint MaxWorkItemDimensions
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS); }
+ }
+
+ public uint[] MaxWorkItemSizes
+ {
+ get {
+ var sizes = Cl.GetInfoArray(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_MAX_WORK_ITEM_SIZES);
+ var result = new uint[sizes.Length];
+ for (var i=0; i(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_MAX_WRITE_IMAGE_ARGS); }
+ }
+
+ public uint MemBaseAddrAlign
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_MEM_BASE_ADDR_ALIGN); }
+ }
+
+ public uint MinDataTypeAlignSize
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE); }
+ }
+
+ public string DeviceCapability
+ {
+ get {
+ try {
+ string Vendor = Cl.GetInfoString(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_VENDOR);
+
+ if(Vendor.IndexOf("nvidia", StringComparison.OrdinalIgnoreCase) >= 0) {
+ string cuda = string.Format("{0}.{1}",Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV),Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV));
+ return cuda;
+ }
+ }
+ catch (OpenClException) {
+ }
+
+ return null;
+ }
+ }
+
+ public string Architecture
+ {
+ get { return Cl.GetInfoString(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_NAME); }
+ }
+
+ public string ComputeCapability
+ {
+ get {
+ try {
+ string Vendor = Cl.GetInfoString(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_VENDOR);
+
+ if(Vendor == "NVIDIA Corporation") {
+ string ComputeCapability_NV_MAJOR = (Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV)).ToString();
+ string ComputeCapability_NV_MINOR = (Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV)).ToString();
+ string ComputeCapability = ComputeCapability_NV_MAJOR + "." + ComputeCapability_NV_MINOR;
+
+ return ComputeCapability;
+
+ }
+ }
+ catch (OpenClException) {
+ }
+
+ return null;
+ }
+ }
+
+ public string Name
+ {
+ get {
+ try {
+ string Name_AMD = Cl.GetInfoString(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_BOARD_NAME_AMD);
+
+ return Name_AMD;
+ }
+ catch (OpenClException) {
+ }
+
+ try {
+ string Vendor = Cl.GetInfoString(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_VENDOR);
+
+ if(Vendor == "NVIDIA Corporation") {
+ string Name_NV = Cl.GetInfoString(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_NAME);
+
+ return Name_NV;
+ }
+ }
+ catch (OpenClException) {
+ }
+
+ return Cl.GetInfoString(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_NAME);
+ }
+ }
+
+ public string ClVersion
+ {
+ get { return Cl.GetInfoString(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_OPENCL_C_VERSION); }
+ }
+
+ public Platform Platform
+ {
+ get {
+ var handle = Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_PLATFORM);
+ return new Platform(handle);
+ }
+ }
+
+ public uint PreferredVectorWidthChar
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR); }
+ }
+
+ public uint PreferredVectorWidthShort
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT); }
+ }
+
+ public uint PreferredVectorWidthInt
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT); }
+ }
+
+ public uint PreferredVectorWidthLong
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG); }
+ }
+
+ public uint PreferredVectorWidthFloat
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT); }
+ }
+
+ public uint PreferredVectorWidthDouble
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE); }
+ }
+
+ public string Profile
+ {
+ get { return Cl.GetInfoString(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_PROFILE); }
+ }
+//
+// CL_DEVICE_PROFILING_TIMER_RESOLUTION
+// Return type: size_t
+//
+// Describes the resolution of device timer. This is measured in nanoseconds.
+
+ public CommandQueueProperties QueueProperties
+ {
+ get { return Cl.GetInfoEnum(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_QUEUE_PROPERTIES); }
+ }
+
+ public FpConfig SingleFpConfig
+ {
+ get { return Cl.GetInfoEnum(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_SINGLE_FP_CONFIG); }
+ }
+
+ public DeviceType Type
+ {
+ get { return Cl.GetInfoEnum(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_TYPE); }
+ }
+
+ public string Vendor
+ {
+ get { return Cl.GetInfoString(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_VENDOR); }
+ }
+
+ public uint VendorId
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_VENDOR_ID); }
+ }
+
+ public string Version
+ {
+ get { return Cl.GetInfoString(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_VERSION); }
+ }
+
+ public string DriverVersion
+ {
+ get { return Cl.GetInfoString(NativeMethods.clGetDeviceInfo, this.handle, CL_DRIVER_VERSION); }
+ }
+
+ public string PCIBusId
+ {
+ get {
+ string Vendor = Cl.GetInfoString(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_VENDOR);
+ uint BusId = 0;
+ uint DevId = 0;
+ bool ok = false;
+
+ if (Vendor.IndexOf("nvidia", StringComparison.OrdinalIgnoreCase) >= 0) {
+ try {
+ BusId = Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_PCI_BUS_ID_NV );
+ DevId = Cl.GetInfo(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_PCI_SLOT_ID_NV) >> 3;
+ ok = true;
+ }
+ catch (OpenClException) {
+ }
+ } else {
+ try {
+ //int type; byte[17] unused; byte bus; byte device; byte function;
+ byte[] PCIBus_AMD = Cl.GetInfoArray(NativeMethods.clGetDeviceInfo, this.handle, CL_DEVICE_TOPOLOGY_AMD);
+
+ if (PCIBus_AMD != null && PCIBus_AMD.Length == 24 && PCIBus_AMD[0] == 1) {
+ BusId = PCIBus_AMD[21];
+ DevId = PCIBus_AMD[22];
+ ok = true;
+ }
+ }
+ catch (OpenClException) {
+ }
+ }
+ return ok? string.Format("{0:X2}:{1:X2}",BusId,DevId) : null;
+ }
+ }
+
+ // static factory methods
+
+ public static Device[] GetDeviceIDs(Platform platform, DeviceType type)
+ {
+ ErrorCode error;
+ uint count;
+
+ error = NativeMethods.clGetDeviceIDs(platform.handle, type, 0, null, out count);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+
+ var ids = new IntPtr[count];
+ error = NativeMethods.clGetDeviceIDs(platform.handle, type, count, ids, out count);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+
+ var res = new Device[count];
+ for (var i=0; i(NativeMethods.clGetEventInfo, this.handle, CL_EVENT_COMMAND_QUEUE);
+ return new CommandQueue(queue);
+ }
+ }
+
+ public CommandType CommandType
+ {
+ get { return Cl.GetInfoEnum(NativeMethods.clGetEventInfo, this.handle, CL_EVENT_COMMAND_TYPE); }
+ }
+
+ public uint ReferenceCount
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetEventInfo, this.handle, CL_EVENT_REFERENCE_COUNT); }
+ }
+
+ public ExecutionStatus ExecutionStatus
+ {
+ get { return Cl.GetInfoEnum(NativeMethods.clGetEventInfo, this.handle, CL_EVENT_COMMAND_EXECUTION_STATUS); }
+ }
+
+ public Context Context
+ {
+ get {
+ var ctx = Cl.GetInfo(NativeMethods.clGetEventInfo, this.handle, CL_EVENT_CONTEXT);
+ return new Context(ctx);
+ }
+ }
+
+ // Event methods
+
+ public static void WaitForEvents(Event[] eventWaitList)
+ {
+ var l = ToIntPtr(eventWaitList);
+ NativeMethods.clWaitForEvents((uint)l.Length, l);
+ }
+
+ // RefCountedObject
+
+ protected override void Retain()
+ {
+ NativeMethods.clRetainEvent(this.handle);
+ }
+
+ protected override void Release()
+ {
+ NativeMethods.clReleaseEvent(this.handle);
+ }
+
+ // utilities
+
+ internal static Event[] FromIntPtr(IntPtr[] arr)
+ {
+ var res = new Event[arr.Length];
+ for (var i=0; i(NativeMethods.clGetKernelInfo, this.handle, CL_KERNEL_NUM_ARGS); }
+ }
+
+ public uint ReferenceCount
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetKernelInfo, this.handle, CL_KERNEL_REFERENCE_COUNT); }
+ }
+
+ public Context Context
+ {
+ get {
+ var ctx = Cl.GetInfo(NativeMethods.clGetKernelInfo, this.handle, CL_KERNEL_CONTEXT);
+ return new Context(ctx);
+ }
+ }
+
+ public Program Program
+ {
+ get {
+ var prog = Cl.GetInfo(NativeMethods.clGetKernelInfo, this.handle, CL_KERNEL_PROGRAM);
+ return new Program(prog);
+ }
+ }
+
+ public string[] Attributes
+ {
+ get {
+ var res = Cl.GetInfoString(NativeMethods.clGetKernelInfo, this.handle, CL_KERNEL_ATTRIBUTES);
+ return res.Split(new char[] { ' ' });
+ }
+ }
+
+ // Kernel methods
+
+ public void SetKernelArg(uint idx, T val) where T: struct
+ {
+ var size = (IntPtr)Marshal.SizeOf();
+ GCHandle gch = GCHandle.Alloc(val, GCHandleType.Pinned);
+ try {
+ var error = NativeMethods.clSetKernelArg(this.handle, idx, size, gch.AddrOfPinnedObject());
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ }
+ finally {
+ gch.Free();
+ }
+ }
+
+ public void SetKernelArg(uint idx, HandleObject val)
+ {
+ var size = (IntPtr)Marshal.SizeOf();
+ IntPtr obj = val.handle;
+ var error = NativeMethods.clSetKernelArg(this.handle, idx, size, ref obj);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ }
+
+ // RefCountedObject
+
+ protected override void Retain()
+ {
+ NativeMethods.clRetainKernel(this.handle);
+ }
+
+ protected override void Release()
+ {
+ NativeMethods.clReleaseKernel(this.handle);
+ }
+
+ // static factory methods
+
+ public static Kernel CreateKernel(Program program, string name)
+ {
+ ErrorCode error;
+ var handle = NativeMethods.clCreateKernel(program.handle, name, out error);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ return new Kernel(handle);
+ }
+
+ public static Kernel[] CreateKernelsInProgram(Program program)
+ {
+ ErrorCode error;
+ uint numKernels;
+ error = NativeMethods.clCreateKernelsInProgram(program.handle, 0, null, out numKernels);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ IntPtr[] kernels = new IntPtr[numKernels];
+ error = NativeMethods.clCreateKernelsInProgram(program.handle, numKernels, kernels, out numKernels);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ return Kernel.FromIntPtr(kernels);
+ }
+
+ // utilities
+
+ internal static Kernel[] FromIntPtr(IntPtr[] arr)
+ {
+ var res = new Kernel[arr.Length];
+ for (var i=0; i))]
+ public sealed class Mem : RefCountedObject, IEquatable> where T: struct
+ {
+ internal Mem(IntPtr handle) : base(handle) { }
+
+ private const uint CL_MEM_TYPE = 0x1100;
+ private const uint CL_MEM_FLAGS = 0x1101;
+ private const uint CL_MEM_SIZE = 0x1102;
+ private const uint CL_MEM_HOST_PTR = 0x1103;
+ private const uint CL_MEM_MAP_COUNT = 0x1104;
+ private const uint CL_MEM_REFERENCE_COUNT = 0x1105;
+ private const uint CL_MEM_CONTEXT = 0x1106;
+ private const uint CL_MEM_ASSOCIATED_MEMOBJECT = 0x1107;
+ private const uint CL_MEM_OFFSET = 0x1108;
+ private const uint CL_MEM_USES_SVM_POINTER = 0x1109;
+
+ // Mem attributes
+
+ public MemObjectType Type
+ {
+ get { return Cl.GetInfoEnum(NativeMethods.clGetMemObjectInfo, this.handle, CL_MEM_TYPE); }
+ }
+
+ public MemFlags Flags
+ {
+ get { return Cl.GetInfoEnum(NativeMethods.clGetMemObjectInfo, this.handle, CL_MEM_FLAGS); }
+ }
+
+ public uint Size
+ {
+ get { return (uint)Cl.GetInfo(NativeMethods.clGetMemObjectInfo, this.handle, CL_MEM_SIZE); }
+ }
+
+ public IntPtr HostPtr
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetMemObjectInfo, this.handle, CL_MEM_HOST_PTR); }
+ }
+
+ public uint MapCount
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetMemObjectInfo, this.handle, CL_MEM_MAP_COUNT); }
+ }
+
+ public uint ReferenceCount
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetMemObjectInfo, this.handle, CL_MEM_REFERENCE_COUNT); }
+ }
+
+ public Context Context
+ {
+ get {
+ var ctx = Cl.GetInfo(NativeMethods.clGetMemObjectInfo, this.handle, CL_MEM_CONTEXT);
+ return new Context(ctx);
+ }
+ }
+
+ public Mem AssociatedMemObject
+ {
+ get {
+ var mem = Cl.GetInfo(NativeMethods.clGetMemObjectInfo, this.handle, CL_MEM_ASSOCIATED_MEMOBJECT);
+ if (mem != IntPtr.Zero) {
+ return new Mem(mem);
+ }
+ else {
+ return null;
+ }
+ }
+ }
+
+ public uint Offset
+ {
+ get { return (uint)Cl.GetInfo(NativeMethods.clGetMemObjectInfo, this.handle, CL_MEM_OFFSET); }
+ }
+
+ public bool UsesSvmPointer
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetMemObjectInfo, this.handle, CL_MEM_USES_SVM_POINTER) != 0; }
+ }
+
+ // RefCountedObject
+
+ protected override void Retain()
+ {
+ NativeMethods.clRetainMemObject(this.handle);
+ }
+
+ protected override void Release()
+ {
+ NativeMethods.clReleaseMemObject(this.handle);
+ }
+
+ // IEquatable
+
+ public bool Equals(Mem other)
+ {
+ return this.handle == other.handle;
+ }
+
+ // static factory methods
+
+ public static Mem CreateBuffer(Context context, T[] data)
+ {
+ return CreateBuffer(context, MemFlags.None, data);
+ }
+
+ public static Mem CreateBuffer(Context context, MemFlags flags, T[] data)
+ {
+ var res = IntPtr.Zero;
+ var gch = GCHandle.Alloc(data, GCHandleType.Pinned);
+ try {
+ var size = (IntPtr)(Marshal.SizeOf()*data.Length);
+ ErrorCode error;
+ res = NativeMethods.clCreateBuffer(context.handle, flags, size, gch.AddrOfPinnedObject(), out error);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ }
+ finally {
+ gch.Free();
+ }
+ return new Mem(res);
+ }
+
+ public static Mem CreateBuffer(Context context, int size)
+ {
+ return CreateBuffer(context, MemFlags.None, size);
+ }
+
+ public static Mem CreateBuffer(Context context, MemFlags flags, int size)
+ {
+ ErrorCode error;
+ var res = NativeMethods.clCreateBuffer(context.handle, flags, (IntPtr)size, IntPtr.Zero, out error);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ return new Mem(res);
+ }
+
+ public static Mem CreateBuffer(Context context, uint size)
+ {
+ return CreateBuffer(context, MemFlags.None, size);
+ }
+
+ public static Mem CreateBuffer(Context context, MemFlags flags, uint size)
+ {
+ ErrorCode error;
+ var res = NativeMethods.clCreateBuffer(context.handle, flags, (IntPtr)size, IntPtr.Zero, out error);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ return new Mem(res);
+ }
+ }
+
+ internal sealed class MemDebugView where T: struct
+ {
+ private readonly Mem mem;
+
+ public MemDebugView(Mem mem)
+ {
+ this.mem = mem;
+ }
+
+ public T[] Values
+ {
+ get {
+// ErrorCode err;
+ var size = this.mem.Size;
+
+ var elemSize = Marshal.SizeOf();
+ var length = size/elemSize;
+ if (length*elemSize < size) {
+ length++;
+ }
+ var result = new T[length];
+
+// var context = this.mem.Context;
+//
+// var devices = context.Devices;
+// var commandQueue = CommandQueue.CreateCommandQueue(context, devices[0], CommandQueueProperties.None);
+//
+// using(var ev = commandQueue.EnqueueReadBuffer(this.mem, true, result));
+
+ return result;
+ }
+ }
+ }
+}
diff --git a/Includes/OpenCL/NativeMethods.cs b/Includes/OpenCL/NativeMethods.cs
new file mode 100644
index 0000000000..150a5c79c0
--- /dev/null
+++ b/Includes/OpenCL/NativeMethods.cs
@@ -0,0 +1,418 @@
+//
+// NativeMethods.cs
+// opencl-sharp
+//
+// Copyright (c) 2016 Markus Uhr. All rights reserved.
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace OpenCl
+{
+ internal class NativeMethods
+ {
+ private NativeMethods()
+ {
+ }
+
+ //
+ // Platform
+ //
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clGetPlatformIDs(uint numEntries, IntPtr[] platforms, out uint numPlatforms);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clGetPlatformInfo(IntPtr platform, uint paramName, IntPtr paramValueSize, IntPtr paramValue, out IntPtr paramValueSizeRet);
+
+ //
+ // Device
+ //
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clGetDeviceIDs(IntPtr platform, DeviceType deviceType, uint numEntries, IntPtr[] devices, out uint numDevices);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clGetDeviceInfo(IntPtr device, uint paramName, IntPtr paramValueSize, IntPtr paramValue, out IntPtr paramValueSizeRet);
+
+ //
+ // Context
+ //
+
+ [DllImport("OpenCL")]
+ internal static extern IntPtr clCreateContext(ContextProperty[] properties, uint numDevices, IntPtr[] devices, ContextNotifyInternal pfnNotify, IntPtr userData, out ErrorCode errcodeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern IntPtr clCreateContextFromType(ContextProperty[] properties, DeviceType deviceType, ContextNotifyInternal pfnNotify, IntPtr userData, out ErrorCode errcodeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clRetainContext(IntPtr context);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clReleaseContext(IntPtr context);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clGetContextInfo(IntPtr context, uint paramName, IntPtr paramValueSize, IntPtr paramValue, out IntPtr paramValueSizeRet);
+
+ //
+ // Program
+ //
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clUnloadCompiler();
+
+ [DllImport("OpenCL")]
+ internal static extern IntPtr clCreateProgramWithSource(
+ IntPtr context,
+ uint count,
+ [In] string[] strings,
+ [In] IntPtr[] lengths,
+ out ErrorCode errcodeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern IntPtr clCreateProgramWithBinary(
+ IntPtr context,
+ uint numDevices,
+ [In] IntPtr[] deviceList,
+ [In] IntPtr[] lengths,
+ [In] IntPtr[] binaries,
+ [Out] int[] binaryStatus,
+ out ErrorCode errcodeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern IntPtr clCreateProgramWithIL(
+ IntPtr context,
+ byte[] binary,
+ IntPtr length,
+ out ErrorCode errcodeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clRetainProgram(IntPtr program);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clReleaseProgram(IntPtr program);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clBuildProgram(IntPtr program, uint numDevices, IntPtr[] deviceList, string options, ProgramNotifyInternal pfnNotify, IntPtr userData);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clGetProgramInfo(IntPtr program, uint paramName, IntPtr paramValueSize, IntPtr paramValue, out IntPtr paramValueSizeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clGetProgramBuildInfo(IntPtr program, IntPtr device, uint paramName, IntPtr paramValueSize, IntPtr paramValue, out IntPtr paramValueSizeRet);
+
+ //
+ // Kernel
+ //
+
+ [DllImport("OpenCL")]
+ internal static extern IntPtr clCreateKernel(IntPtr program, string kernelName, out ErrorCode errcodeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clCreateKernelsInProgram(IntPtr program, uint numKernels, IntPtr[] kernels, out uint numKernelsRet);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clRetainKernel(IntPtr kernel);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clReleaseKernel(IntPtr kernel);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clSetKernelArg(IntPtr kernel, uint argIndex, IntPtr argSize, IntPtr argValue);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clSetKernelArg(IntPtr kernel, uint argIndex, IntPtr argSize, ref IntPtr argValue);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clGetKernelInfo(IntPtr kernel, uint paramName, IntPtr paramValueSize, IntPtr paramValue, out IntPtr paramValueSizeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clGetKernelWorkGroupInfo(IntPtr kernel, IntPtr device, KernelWorkGroupInfo paramName, IntPtr paramValueSize, IntPtr paramValue, out IntPtr paramValueSizeRet);
+
+ //
+ // Mem
+ //
+
+ [DllImport("OpenCL")]
+ internal static extern IntPtr clCreateBuffer(IntPtr context, MemFlags flags, IntPtr size, IntPtr hostPtr, [Out] [MarshalAs(UnmanagedType.I4)] out ErrorCode errcodeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clRetainMemObject(IntPtr memObj);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clReleaseMemObject(IntPtr memObj);
+
+// [DllImport("OpenCL")]
+// internal static extern ErrorCode clGetSupportedImageFormats(IntPtr context, MemFlags flags, MemObjectType imageType, uint numEntries, [Out] [MarshalAs(UnmanagedType.LPArray)] ImageFormat[] imageFormats, out uint numImageFormats);
+
+ [DllImport("OpenCL")]
+ internal static extern IntPtr clCreateImage2D(IntPtr context, MemFlags flags, IntPtr imageFormat, IntPtr imageWidth, IntPtr imageHeight, IntPtr imageRowPitch, IntPtr hostPtr, out ErrorCode errcodeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern IntPtr clCreateImage3D(IntPtr context, MemFlags flags, IntPtr imageFormat, IntPtr imageWidth, IntPtr imageHeight, IntPtr imageDepth, IntPtr imageRowPitch, IntPtr imageSlicePitch, IntPtr hostPtr, out ErrorCode errcodeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clGetMemObjectInfo(IntPtr memObj, uint paramName, IntPtr paramValueSize, IntPtr paramValue, out IntPtr paramValueSizeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clGetImageInfo(IntPtr image, ImageInfo paramName, IntPtr paramValueSize, IntPtr paramValue, out IntPtr paramValueSizeRet);
+
+ //
+ // CommandQueue
+ //
+
+ [DllImport("OpenCL")]
+ internal static extern IntPtr clCreateCommandQueue(IntPtr context, IntPtr device, [MarshalAs(UnmanagedType.U8)] CommandQueueProperties properties, out ErrorCode error);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clRetainCommandQueue(IntPtr commandQueue);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clReleaseCommandQueue(IntPtr commandQueue);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clGetCommandQueueInfo(IntPtr commandQueue, uint paramName, IntPtr paramValueSize, IntPtr paramValue, out IntPtr paramValueSizeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clSetCommandQueueProperty(IntPtr commandQueue, [MarshalAs(UnmanagedType.U8)] CommandQueueProperties properties, bool enable, [MarshalAs(UnmanagedType.U8)] out CommandQueueProperties oldProperties);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueReadBuffer(
+ IntPtr commandQueue,
+ IntPtr buffer,
+ uint blockingRead,
+ IntPtr offsetInBytes,
+ IntPtr lengthInBytes,
+ IntPtr ptr,
+ uint numEventsInWaitList,
+ IntPtr[] eventWaitList,
+ out IntPtr e);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueWriteBuffer(
+ IntPtr commandQueue,
+ IntPtr buffer,
+ uint blockingWrite,
+ IntPtr offsetInBytes,
+ IntPtr lengthInBytes,
+ IntPtr ptr,
+ uint numEventsInWaitList,
+ IntPtr[] eventWaitList,
+ out IntPtr e);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueFillBuffer(
+ IntPtr commandQueue,
+ IntPtr buffer,
+ IntPtr pattern,
+ IntPtr patternSize,
+ IntPtr offsetInBytes,
+ IntPtr sizeInBytes,
+ uint numEventsInWaitList,
+ IntPtr[] eventWaitList,
+ out IntPtr e);
+
+ // [DllImport("OpenCL")]
+ // internal static extern ErrorCode clEnqueueFillBuffer(
+ // IntPtr commandQueue,
+ // IntPtr buffer,
+ // ref X pattern,
+ // IntPtr patternSize,
+ // IntPtr offsetInBytes,
+ // IntPtr sizeInBytes,
+ // uint numEventsInWaitList,
+ // IntPtr[] eventWaitList,
+ // out IntPtr e);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueCopyBuffer(
+ IntPtr commandQueue,
+ IntPtr srcBuffer,
+ IntPtr dstBuffer,
+ IntPtr srcOffset,
+ IntPtr dstOffset,
+ IntPtr cb,
+ uint numEventsInWaitList,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt, SizeParamIndex = 6)] Event[] eventWaitList,
+ [Out] [MarshalAs(UnmanagedType.Struct)] out Event e);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueReadImage(IntPtr commandQueue,
+ IntPtr image,
+ uint blockingRead,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] IntPtr[] origin,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] IntPtr[] region,
+ IntPtr rowPitch,
+ IntPtr slicePitch,
+ IntPtr ptr,
+ uint numEventsIntWaitList,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt, SizeParamIndex = 8)] Event[] eventWaitList,
+ [Out] [MarshalAs(UnmanagedType.Struct)] out Event e);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueWriteImage(IntPtr commandQueue,
+ IntPtr image,
+ uint blockingWrite,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] IntPtr[] origin,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] IntPtr[] region,
+ IntPtr rowPitch,
+ IntPtr slicePitch,
+ IntPtr ptr,
+ uint numEventsIntWaitList,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt, SizeParamIndex = 8)] Event[] eventWaitList,
+ [Out] [MarshalAs(UnmanagedType.Struct)] out Event e);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueCopyImage(IntPtr commandQueue,
+ IntPtr srcImage,
+ IntPtr dstImage,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] IntPtr[] srcOrigin,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] IntPtr[] dstOrigin,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] IntPtr[] region,
+ uint numEventsInWaitList,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt, SizeParamIndex = 6)] Event[] eventWaitList,
+ [Out] [MarshalAs(UnmanagedType.Struct)] out Event e);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueCopyImageToBuffer(IntPtr commandQueue,
+ IntPtr srcImage,
+ IntPtr dstBuffer,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] IntPtr[] srcOrigin,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] IntPtr[] region,
+ IntPtr dstOffset,
+ uint numEventsInWaitList,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt, SizeParamIndex = 6)] Event[] eventWaitList,
+ [Out] [MarshalAs(UnmanagedType.Struct)] out Event e);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueCopyBufferToImage(IntPtr commandQueue,
+ IntPtr srcBuffer,
+ IntPtr dstImage,
+ IntPtr srcOffset,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] IntPtr[] dstOrigin,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] IntPtr[] region,
+ uint numEventsInWaitList,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt, SizeParamIndex = 6)] Event[] eventWaitList,
+ [Out] [MarshalAs(UnmanagedType.Struct)] out Event e);
+
+ [DllImport("OpenCL")]
+ internal static extern IntPtr clEnqueueMapBuffer(IntPtr commandQueue,
+ IntPtr buffer,
+ uint blockingMap,
+ MapFlags mapFlags,
+ IntPtr offset,
+ IntPtr cb,
+ uint numEventsInWaitList,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt, SizeParamIndex = 6)] Event[] eventWaitList,
+ [Out] [MarshalAs(UnmanagedType.Struct)] out Event e,
+ out ErrorCode errCodeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern IntPtr clEnqueueMapImage(IntPtr commandQueue,
+ IntPtr image,
+ uint blockingMap,
+ MapFlags mapFlags,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] IntPtr[] origin,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeConst = 3)] IntPtr[] region,
+ out IntPtr imageRowPitch,
+ out IntPtr imageSlicePitch,
+ uint numEventsInWaitList,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt, SizeParamIndex = 8)] Event[] eventWaitList,
+ [Out] [MarshalAs(UnmanagedType.Struct)] out Event e,
+ out ErrorCode errCodeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueUnmapMemObject(IntPtr commandQueue,
+ IntPtr memObj,
+ IntPtr mappedPtr,
+ uint numEventsInWaitList,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt, SizeParamIndex = 3)] Event[] eventWaitList,
+ [Out] [MarshalAs(UnmanagedType.Struct)] out Event e);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueNDRangeKernel(
+ IntPtr commandQueue,
+ IntPtr kernel,
+ uint workDim,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] IntPtr[] globalWorkOffset,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] IntPtr[] globalWorkSize,
+ [In] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] IntPtr[] localWorkSize,
+ uint numEventsInWaitList,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt, SizeParamIndex = 6)] Event[] eventWaitList,
+ [Out] out IntPtr e);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueNDRangeKernel(
+ IntPtr commandQueue,
+ IntPtr kernel,
+ uint workDim,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt)] uint[] globalWorkOffset,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt)] uint[] globalWorkSize,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt)] uint[] localWorkSize,
+ uint numEventsInWaitList,
+ IntPtr[] eventWaitList,
+ [Out] out IntPtr e);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueNDRangeKernel(
+ IntPtr commandQueue,
+ IntPtr kernel,
+ int workDim,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt)] int[] globalWorkOffset,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt)] int[] globalWorkSize,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt)] int[] localWorkSize,
+ int numEventsInWaitList,
+ IntPtr[] eventWaitList,
+ [Out] out IntPtr e);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueTask(
+ IntPtr commandQueue,
+ IntPtr kernel,
+ uint numEventsInWaitList,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt, SizeParamIndex = 2)] Event[] eventWaitList,
+ [Out] [MarshalAs(UnmanagedType.Struct)] out Event e);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueMarker(
+ IntPtr commandQueue,
+ [Out] [MarshalAs(UnmanagedType.Struct)] out Event e);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueWaitForEvents(
+ IntPtr commandQueue,
+ uint numEventsInWaitList,
+ [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt, SizeParamIndex = 1)] Event[] eventWaitList);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clEnqueueBarrier(IntPtr commandQueue);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clFinish(IntPtr commandQueue);
+
+ //
+ // Event
+ //
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clWaitForEvents(uint numEvents, IntPtr[] eventWaitList);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clGetEventInfo(IntPtr e, uint paramName, IntPtr paramValueSize, IntPtr paramValue, out IntPtr paramValueSizeRet);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clRetainEvent(IntPtr e);
+
+ [DllImport("OpenCL")]
+ internal static extern ErrorCode clReleaseEvent(IntPtr e);
+
+ //
+ // Extension Functions
+ //
+
+ [DllImport("OpenCL")]
+ internal static extern IntPtr clGetExtensionFunctionAddressForPlatform(IntPtr platform, string name);
+
+ }
+}
diff --git a/Includes/OpenCL/OpenClException.cs b/Includes/OpenCL/OpenClException.cs
new file mode 100644
index 0000000000..eb40808986
--- /dev/null
+++ b/Includes/OpenCL/OpenClException.cs
@@ -0,0 +1,33 @@
+using System;
+
+namespace OpenCl
+{
+ public class OpenClException : System.Exception
+ {
+ private ErrorCode code;
+
+ public OpenClException(ErrorCode code)
+ : base(String.Format("OpenCl error {0}: {1}.", (int)code, code.ToString()))
+ {
+ this.code = code;
+ }
+
+ public OpenClException(ErrorCode error, string message)
+ : base(message)
+ {
+ this.code = error;
+ }
+
+ public OpenClException(ErrorCode error, string message, Exception inner)
+ : base(message, inner)
+ {
+ this.code = error;
+ }
+
+ public ErrorCode ErrorCode
+ {
+ get { return this.code; }
+ }
+ }
+}
+
diff --git a/Includes/OpenCL/Platform.cs b/Includes/OpenCL/Platform.cs
new file mode 100644
index 0000000000..80f4265ba7
--- /dev/null
+++ b/Includes/OpenCL/Platform.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace OpenCl
+{
+ public sealed class Platform : HandleObject
+ {
+ private const uint CL_PLATFORM_PROFILE = 0x0900;
+ private const uint CL_PLATFORM_VERSION = 0x0901;
+ private const uint CL_PLATFORM_NAME = 0x0902;
+ private const uint CL_PLATFORM_VENDOR = 0x0903;
+ private const uint CL_PLATFORM_EXTENSIONS = 0x0904;
+ private const uint CL_PLATFORM_HOST_TIMER_RESOLUTION = 0x0905;
+
+ internal Platform(IntPtr handle) : base(handle) { }
+
+ // Platform attributes
+
+ public string Profile
+ {
+ get { return Cl.GetInfoString(NativeMethods.clGetPlatformInfo, this.handle, CL_PLATFORM_PROFILE); }
+ }
+
+ public string Version
+ {
+ get { return Cl.GetInfoString(NativeMethods.clGetPlatformInfo, this.handle, CL_PLATFORM_VERSION); }
+ }
+
+ public string Name
+ {
+ get { return Cl.GetInfoString(NativeMethods.clGetPlatformInfo, this.handle, CL_PLATFORM_NAME); }
+ }
+
+ public string Vendor
+ {
+ get { return Cl.GetInfoString(NativeMethods.clGetPlatformInfo, this.handle, CL_PLATFORM_VENDOR); }
+ }
+
+ public string[] Extensions
+ {
+ get {
+ var res = Cl.GetInfoString(NativeMethods.clGetPlatformInfo, this.handle, CL_PLATFORM_EXTENSIONS);
+ return res.Split(new char[] { ' ' });
+ }
+ }
+
+ public T GetExtensionFunction(string name) where T : class
+ {
+ IntPtr addr = NativeMethods.clGetExtensionFunctionAddressForPlatform(this.handle, name);
+ if (addr == IntPtr.Zero) {
+ return null;
+ }
+ return Marshal.GetDelegateForFunctionPointer(addr, typeof(T)) as T;
+ }
+
+ // static factory method
+
+ public static Platform[] GetPlatformIDs()
+ {
+ ErrorCode error;
+ uint count;
+
+ error = NativeMethods.clGetPlatformIDs(0, null, out count);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+
+ var ids = new IntPtr[count] ;
+ error = NativeMethods.clGetPlatformIDs(count, ids, out count);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+
+ var res = new Platform[count];
+ for (var i=0; i(NativeMethods.clGetProgramBuildInfo, this.owner.handle, device.handle, CL_PROGRAM_BUILD_STATUS);
+ }
+
+ public string GetOptions(Device device)
+ {
+ return Cl.GetBuildInfoString(NativeMethods.clGetProgramBuildInfo, this.owner.handle, device.handle, CL_PROGRAM_BUILD_OPTIONS);
+ }
+
+ public string GetLog(Device device)
+ {
+ return Cl.GetBuildInfoString(NativeMethods.clGetProgramBuildInfo, this.owner.handle, device.handle, CL_PROGRAM_BUILD_LOG);
+ }
+
+ public BinaryType GetBinaryType(Device device)
+ {
+ return Cl.GetBuildInfoEnum(NativeMethods.clGetProgramBuildInfo, this.owner.handle, device.handle, CL_PROGRAM_BINARY_TYPE);
+ }
+ }
+
+ public sealed class Program : RefCountedObject
+ {
+ private const uint CL_PROGRAM_REFERENCE_COUNT = 0x1160;
+ private const uint CL_PROGRAM_CONTEXT = 0x1161;
+ private const uint CL_PROGRAM_NUM_DEVICES = 0x1162;
+ private const uint CL_PROGRAM_DEVICES = 0x1163;
+ private const uint CL_PROGRAM_SOURCE = 0x1164;
+ private const uint CL_PROGRAM_BINARY_SIZES = 0x1165;
+ private const uint CL_PROGRAM_BINARIES = 0x1166;
+ private const uint CL_PROGRAM_NUM_KERNELS = 0x1167;
+ private const uint CL_PROGRAM_KERNEL_NAMES = 0x1168;
+ private const uint CL_PROGRAM_IL = 0x1169;
+
+ internal Program(IntPtr handle) : base(handle) { }
+
+ // Program attributes
+
+ public uint ReferenceCount
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetProgramInfo, this.handle, CL_PROGRAM_REFERENCE_COUNT); }
+ }
+
+ public Context Context
+ {
+ get {
+ var ctx = Cl.GetInfo(NativeMethods.clGetProgramInfo, this.handle, CL_PROGRAM_CONTEXT);
+ return new Context(ctx);
+ }
+ }
+
+ public uint NumDevices
+ {
+ get { return Cl.GetInfo(NativeMethods.clGetProgramInfo, this.handle, CL_PROGRAM_NUM_DEVICES); }
+ }
+
+ public Device[] Devices
+ {
+ get { return Device.FromIntPtr(Cl.GetInfoArray(NativeMethods.clGetProgramInfo, this.handle, CL_PROGRAM_DEVICES)); }
+ }
+
+ public string Source
+ {
+ get { return Cl.GetInfoString(NativeMethods.clGetProgramInfo, this.handle, CL_PROGRAM_SOURCE); }
+ }
+
+ public IntPtr[] BinarySizes
+ {
+ get { return Cl.GetInfoArray(NativeMethods.clGetProgramInfo, this.handle, CL_PROGRAM_BINARY_SIZES); }
+ }
+
+ public byte[][] Binaries
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ public int NumKernels
+ {
+ get { return (int)Cl.GetInfo(NativeMethods.clGetProgramInfo, this.handle, CL_PROGRAM_NUM_KERNELS); }
+ }
+
+ public String[] KernelNames
+ {
+ get {
+ var names = Cl.GetInfoString(NativeMethods.clGetProgramInfo, this.handle, CL_PROGRAM_KERNEL_NAMES);
+ return names.Split(new char[] { ';' });
+ }
+ }
+
+ // Program build attributes
+
+ private BuildInfo bi;
+
+ public BuildInfo BuildInfo
+ {
+ get {
+ if (this.bi == null) {
+ this.bi = new BuildInfo(this);
+ }
+ return this.bi;
+ }
+ }
+
+ // Program methods
+
+ public void BuildProgram(Device device)
+ {
+ BuildProgram(device, null, null, null);
+ }
+
+ public void BuildProgram(Device device, string options)
+ {
+ BuildProgram(device, options, null, null);
+ }
+
+ public void BuildProgram(Device device, string options, ProgramNotify callback, object userData)
+ {
+ var dev = Device.ToIntPtr(device);
+ var pfn = (ProgramNotifyData)null;
+ var pcb = (ProgramNotifyInternal)null;
+ var ptr = IntPtr.Zero;
+ if (callback != null) {
+ pfn = new ProgramNotifyData(callback, userData);
+ pcb = ProgramNotifyData.Callback;
+ ptr = GCHandle.ToIntPtr(pfn.Handle);
+ }
+ var err = NativeMethods.clBuildProgram(this.handle, (uint)dev.Length, dev, options, pcb, ptr);
+ if (err != ErrorCode.Success) {
+ throw new OpenClException(err);
+ }
+ }
+
+ public void BuildProgram(Device[] deviceList)
+ {
+ BuildProgram(deviceList, null, null, null);
+ }
+
+ public void BuildProgram(Device[] deviceList, string options)
+ {
+ BuildProgram(deviceList, options, null, null);
+ }
+
+ public void BuildProgram(Device[] deviceList, string options, ProgramNotify callback, object userData)
+ {
+ var dev = Device.ToIntPtr(deviceList);
+ var pfn = (ProgramNotifyData)null;
+ var pcb = (ProgramNotifyInternal)null;
+ var ptr = IntPtr.Zero;
+ if (callback != null) {
+ pfn = new ProgramNotifyData(callback, userData);
+ pcb = ProgramNotifyData.Callback;
+ ptr = GCHandle.ToIntPtr(pfn.Handle);
+ }
+ var err = NativeMethods.clBuildProgram(this.handle, (uint)dev.Length, dev, options, pcb, ptr);
+ if (err != ErrorCode.Success) {
+ throw new OpenClException(err);
+ }
+ }
+
+ // RefCountedObject
+
+ protected override void Retain()
+ {
+ NativeMethods.clRetainProgram(this.handle);
+ }
+
+ protected override void Release()
+ {
+ NativeMethods.clReleaseProgram(this.handle);
+ }
+
+ // static factory methods
+
+ public static Program CreateProgramWithSource(Context context, string[] sources)
+ {
+ ErrorCode error;
+ IntPtr[] buffers = new IntPtr[sources.Length];
+ for (var i=0; i)binaries).Select(b => (IntPtr)b.Length).ToArray();
+ var handle = IntPtr.Zero;
+ GCHandle[] hbins = binaries.Select(b => GCHandle.Alloc(b, GCHandleType.Pinned)).ToArray();
+ try {
+ handle = NativeMethods.clCreateProgramWithBinary(context.handle, (uint)deviceList.Length, dev, lengths, hbins.Select(h => h.AddrOfPinnedObject()).ToArray(), null, out error);
+ } finally {
+ foreach (var h in hbins) {
+ h.Free();
+ }
+ }
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ return new Program(handle);
+ }
+
+#if CL_KHR_IL_PROGRAM
+ delegate IntPtr ClCreateProgramWithILKHR(IntPtr handle, byte[] buf, IntPtr len, out ErrorCode error);
+
+ public static Program CreateProgramWithILKHR(Context context, byte[] binary)
+ {
+ Device[] devs = context.Devices;
+ Platform pfrm = devs[0].Platform;
+ var func = context.Devices[0].Platform.GetExtensionFunction("clCreateProgramWithILKHR");
+ if (func == null) {
+ Console.WriteLine("Function 'clCreateProgramWithILKHR' not found.");
+ return null;
+ }
+ ErrorCode error;
+ IntPtr length = (IntPtr)binary.Length;
+ var handle = func.Invoke(context.handle, binary, length, out error);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ return new Program(handle);
+ }
+
+ public static Program CreateProgramWithILKHR(Context context, Device device, byte[] binary)
+ {
+ var result = CreateProgramWithILKHR(context, binary);
+ result.BuildProgram(device);
+ return result;
+ }
+
+#endif
+ public static Program CreateProgramWithIL(Context context, byte[] binary)
+ {
+ ErrorCode error;
+ IntPtr length = (IntPtr)binary.Length;
+ var handle = NativeMethods.clCreateProgramWithIL(context.handle, binary, length, out error);
+ if (error != ErrorCode.Success) {
+ throw new OpenClException(error);
+ }
+ return new Program(handle);
+ }
+
+ public static Program CreateProgramWithIL(Context context, Device device, byte[] binary)
+ {
+ var result = CreateProgramWithIL(context, binary);
+ result.BuildProgram(device);
+ return result;
+ }
+
+ public static Program CreateProgramWithExpression(Context context, Expression[] expressions)
+ {
+ var n = expressions.Length;
+ var sources = new string[n];
+ for (var i=0; i})) { Return }
+
+$Uri = "https://github.com/Minerx117/miner-binaries/releases/download/5.0.3/ttminer503.7z"
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$Path = ".\Bin\$($Name)\TT-Miner.exe"
+$DeviceEnumerator = "Type_Vendor_Index"
+
+$Algorithms = [PSCustomObject[]]@(
+ [PSCustomObject]@{ Algorithm = "Eaglesong"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 0); Arguments = " -algo EAGLESONG" }
+ [PSCustomObject]@{ Algorithm = "Ethash"; MinMemGB = ($Pools."Ethash".DAGSize + 0.8GB) / 1GB; MinerSet = 0; WarmupTimes = @(45, 30); Arguments = " -algo ETHASH -intensity 15" } # PhoenixMiner-v6.1b may be faster, but I see lower speed at the pool
+ [PSCustomObject]@{ Algorithm = "EthashLowMem"; MinMemGB = ($Pools."EthashLowMem".DAGSize + 0.8GB) / 1GB; MinerSet = 0; WarmupTimes = @(45, 30); Arguments = " -algo ETHASH -intensity 15" } # PhoenixMiner-v6.1b may be faster, but I see lower speed at the pool
+ [PSCustomObject]@{ Algorithm = "KawPoW"; MinMemGB = ($Pools."KawPoW".DAGSize + 0.8GB) / 1GB; MinerSet = 0; WarmupTimes = @(40, 30); Arguments = " -algo KAWPOW" }
+ [PSCustomObject]@{ Algorithm = "Lyra2RE3"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 0); Arguments = " -algo LYRA2V3" }
+ [PSCustomObject]@{ Algorithm = "MTP"; MinMemGB = 3; MinerSet = 0; WarmupTimes = @(30, 0); Arguments = " -algo MTP -intensity 21" } # CcminerMTP-v1.3.2 is faster
+ [PSCustomObject]@{ Algorithm = "ProgPoW"; MinMemGB = ($Pools."ProgPoW".DAGSize + 0.8GB) / 1GB; MinerSet = 0; WarmupTimes = @(45, 30); Arguments = " -algo PROGPOW" } # Zano, Sero
+ [PSCustomObject]@{ Algorithm = "UbqHash"; MinMemGB = ($Pools."UbqHash".DAGSize + 0.8GB) / 1GB; MinerSet = 0; WarmupTimes = @(45, 30); Arguments = " -algo UBQHASH -intensity 15" }
+)
+
+If ($Algorithms = $Algorithms | Where-Object MinerSet -LE $Config.MinerSet | Where-Object { $Pools.($_.Algorithm).Host }) {
+
+ $Devices | Select-Object Model -Unique | ForEach-Object {
+
+ $Miner_Devices = $Devices | Where-Object Model -EQ $_.Model
+
+ $MinerAPIPort = [UInt16]($Config.APIPort + ($Miner_Devices | Sort-Object Id | Select-Object -First 1 -ExpandProperty Id) * 2 + 1)
+
+ $Algorithms | ConvertTo-Json | ConvertFrom-Json | ForEach-Object {
+
+ If ($Pools.($_.Algorithm).Epoch -gt 384) { Return }
+
+ If ($AvailableMiner_Devices = $Miner_Devices | Where-Object MemoryGB -ge $_.MinMemGB) {
+
+ $Miner_Name = (@($Name) + @($AvailableMiner_Devices.Model | Sort-Object -Unique | ForEach-Object { $Model = $_; "$(@($AvailableMiner_Devices | Where-Object Model -EQ $Model).Count)x$Model" }) | Select-Object) -join '-' -replace ' '
+
+ If ($AvailableMiner_Devices | Where-Object MemoryGB -le 2) { $_.Arguments = $_.Arguments -replace " -intensity [0-9\.]+" }
+
+ # Get arguments for available miner devices
+ # $_.Arguments = Get-ArgumentsPerDevice -Arguments $_.Arguments -ExcludeArguments @("algo") -DeviceIDs $AvailableMiner_Devices.$DeviceEnumerator
+
+ If ($Pools.($_.Algorithm).Currency -in @("CLO", "ETC", "ETH", "EPIC", "ETP", "EXP", "MUSIC", "PIRL", "RVN", "SERO", "TCR", "UBQ", "VBK", "VEIL", "ZANO", "ZCOIN", "ZELS")) {
+ $_.Arguments += " -coin $($Pools.($_.Algorithm).Currency)"
+ }
+ ElseIf ($_.Algorithm -eq "ProgPoW") { # No coin
+ Return
+ }
+
+ $_.Arguments += " -pool stratum+tcp://$($Pools.($_.Algorithm).Host):$($Pools.($_.Algorithm).Port) -user $($Pools.($_.Algorithm).User)"
+ $_.Arguments += " -pass $($Pools.($_.Algorithm).Pass)$(If ($Pools.($_.Algorithm).BaseName -eq "ProHashing" -and $_.Algorithm -eq "EthashLowMem") { ",l=$((($AvailableMiner_Devices.Memory | Measure-Object -Minimum).Minimum - 0.95GB) / 1GB)" })"
+
+ [PSCustomObject]@{
+ Name = $Miner_Name
+ DeviceName = $AvailableMiner_Devices.Name
+ Type = $AvailableMiner_Devices.Type
+ Path = $Path
+ Arguments = ("$($_.Arguments) -PRT 1 -PRS 0 -api-bind 127.0.0.1:$($MinerAPIPort) -device $(($AvailableMiner_Devices.$DeviceEnumerator | Sort-Object -Unique | ForEach-Object { '{0:x}' -f $_ }) -join ',')" -replace "\s+", " ").trim()
+ Algorithm = $_.Algorithm
+ API = "EthMiner"
+ Port = $MinerAPIPort
+ URI = $Uri
+ Fee = $_.Fee
+ WarmupTimes = $_.WarmupTimes # First value: seconds until miner must send first sample, if no sample is received miner will be marked as failed; Second value: seconds until miner sends stable hashrates that will count for benchmarking
+ }
+ }
+ }
+ }
+}
diff --git a/Miners/TTMiner-v6.2.0.ps1 b/Miners/TTMiner-v6.2.0.ps1
new file mode 100644
index 0000000000..fc9f5dc469
--- /dev/null
+++ b/Miners/TTMiner-v6.2.0.ps1
@@ -0,0 +1,67 @@
+using module ..\Includes\Include.psm1
+
+If (-not ($Devices = $Variables.EnabledDevices | Where-Object Type -EQ "NVIDIA")) { Return }
+If ($Config.MinerInstancePerDeviceModel -and ($Devices.Model | Select-Object -Unique).Count -gt 1) { Return } # Error 'No cuda shared libraries found' if more than one active instance
+
+$Uri = "https://github.com/Minerx117/miners/releases/download/TT-Miner/TT-Miner-v6.2.0.7z"
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$Path = ".\Bin\$($Name)\TT-Miner.exe"
+$DeviceEnumerator = "Type_Vendor_Index"
+
+$Algorithms = [PSCustomObject[]]@(
+ [PSCustomObject]@{ Algorithm = "EtcHash"; Fee = 0.01; MinMemGB = ($Pools."EtcHash".DAGSize + 0.8GB) / 1GB; MinerSet = 1; WarmupTimes = @(45, 30); Arguments = " -algo ETHASH -coin ETC -intensity 15" } # PhoenixMiner-v6.1b is fastest
+ [PSCustomObject]@{ Algorithm = "Ethash"; Fee = 0.01; MinMemGB = ($Pools."Ethash".DAGSize + 0.8GB) / 1GB; MinerSet = 1; WarmupTimes = @(45, 30); Arguments = " -algo ETHASH -intensity 15" } # PhoenixMiner-v6.1b is fastest
+ [PSCustomObject]@{ Algorithm = "EthashLowMem"; Fee = 0.01; MinMemGB = ($Pools."EthashLowMem".DAGSize + 0.8GB) / 1GB; MinerSet = 1; WarmupTimes = @(45, 30); Arguments = " -algo ETHASH -intensity 15" } # PhoenixMiner-v6.1b is fastest
+ [PSCustomObject]@{ Algorithm = "KawPoW"; Fee = 0.01; MinMemGB = ($Pools."KawPoW".DAGSize + 0.8GB) / 1GB; MinerSet = 1; WarmupTimes = @(60, 30); Arguments = " -algo KAWPOW -intensity 15" } # Trex-v0.25.12 is fastest
+ [PSCustomObject]@{ Algorithm = "MTP"; Fee = 0.01; MinMemGB = 3; MinerSet = 1; WarmupTimes = @(45, 30); Arguments = " -algo MTP -intensity 21" } # CcminerMTP-v1.3.2 is faster
+ [PSCustomObject]@{ Algorithm = "ProgPoW"; Fee = 0.01; MinMemGB = ($Pools."ProgPoW".DAGSize + 0.8GB) / 1GB; MinerSet = 1; WarmupTimes = @(45, 30); Arguments = " -algo PROGPOW" } # Sero
+ [PSCustomObject]@{ Algorithm = "UbqHash"; Fee = 0.01; MinMemGB = ($Pools."UbqHash".DAGSize + 0.8GB) / 1GB; MinerSet = 1; WarmupTimes = @(45, 30); Arguments = " -algo UBQHASH -intensity 15" }
+ [PSCustomObject]@{ Algorithm = "Zano"; Fee = 0.01; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 30); Arguments = " -algo PROGPOWZ" }
+)
+
+If ($Algorithms = $Algorithms | Where-Object MinerSet -LE $Config.MinerSet | Where-Object { $Pools.($_.Algorithm).Host }) {
+
+ $Devices | Select-Object Model -Unique | ForEach-Object {
+
+ $Miner_Devices = $Devices | Where-Object Model -EQ $_.Model
+
+ $MinerAPIPort = [UInt16]($Config.APIPort + ($Miner_Devices | Sort-Object Id | Select-Object -First 1 -ExpandProperty Id) * 2 + 1)
+
+ $Algorithms | ConvertTo-Json | ConvertFrom-Json | ForEach-Object {
+
+ If ($AvailableMiner_Devices = $Miner_Devices | Where-Object MemoryGB -ge $_.MinMemGB) {
+
+ $Miner_Name = (@($Name) + @($AvailableMiner_Devices.Model | Sort-Object -Unique | ForEach-Object { $Model = $_; "$(@($AvailableMiner_Devices | Where-Object Model -EQ $Model).Count)x$Model" }) | Select-Object) -join '-' -replace ' '
+
+ If ($AvailableMiner_Devices | Where-Object MemoryGB -le 2) { $_.Arguments = $_.Arguments -replace " -intensity [0-9\.]+" }
+
+ # Get arguments for available miner devices
+ # $_.Arguments = Get-ArgumentsPerDevice -Arguments $_.Arguments -ExcludeArguments @("algo") -DeviceIDs $AvailableMiner_Devices.$DeviceEnumerator
+
+ If ($Pools.($_.Algorithm).Currency -in @("CLO", "ETC", "ETH", "EPIC", "ETP", "EXP", "MUSIC", "PIRL", "RVN", "SERO", "TCR", "UBQ", "VBK", "VEIL", "ZANO", "ZCOIN", "ZELS")) {
+ $_.Arguments += " -coin $($Pools.($_.Algorithm).Currency)"
+ }
+ ElseIf ($_.Algorithm -eq "ProgPoW") { # No coin
+ Return
+ }
+
+ $_.Arguments += " -pool stratum+tcp://$($Pools.($_.Algorithm).Host):$($Pools.($_.Algorithm).Port) -user $($Pools.($_.Algorithm).User)"
+ $_.Arguments += " -pass $($Pools.($_.Algorithm).Pass)$(If ($Pools.($_.Algorithm).BaseName -eq "ProHashing" -and $_.Algorithm -eq "EthashLowMem") { ",l=$((($AvailableMiner_Devices.Memory | Measure-Object -Minimum).Minimum - $1.5GB) / 1GB)" })"
+
+ [PSCustomObject]@{
+ Name = $Miner_Name
+ DeviceName = $AvailableMiner_Devices.Name
+ Type = $AvailableMiner_Devices.Type
+ Path = $Path
+ Arguments = ("$($_.Arguments) -PRT 1 -PRS 0 -api-bind 127.0.0.1:$($MinerAPIPort) -device $(($AvailableMiner_Devices.$DeviceEnumerator | Sort-Object -Unique | ForEach-Object { '{0:x}' -f $_ }) -join ',')" -replace "\s+", " ").trim()
+ Algorithm = $_.Algorithm
+ API = "EthMiner"
+ Port = $MinerAPIPort
+ URI = $Uri
+ Fee = $_.Fee
+ WarmupTimes = $_.WarmupTimes # First value: seconds until miner must send first sample, if no sample is received miner will be marked as failed; Second value: seconds until miner sends stable hashrates that will count for benchmarking
+ }
+ }
+ }
+ }
+}
diff --git a/Miners/TeamBlackMiner-v1.62.ps1 b/Miners/TeamBlackMiner-v1.62.ps1
new file mode 100644
index 0000000000..3aa7dee406
--- /dev/null
+++ b/Miners/TeamBlackMiner-v1.62.ps1
@@ -0,0 +1,71 @@
+using module ..\Includes\Include.psm1
+
+If (-not ($Devices = $Variables.EnabledDevices | Where-Object { $_.Type -eq "AMD" -or ($_.Type -eq "NVIDIA" -and $_.OpenCl.ComputeCapability -ge "5.0") })) { Return }
+
+$Uri = Switch ($Variables.DriverVersion.CUDA) {
+ # { $_ -ge "11.6" } { "https://github.com/sp-hash/TeamBlackMiner/releases/download/v1.58/TeamBlackMiner_1_58_cuda_11_6.7z"; Break }
+ { $_ -ge "11.5" } { "https://github.com/sp-hash/TeamBlackMiner/releases/download/v1.62/TeamBlackMiner_1_62_cuda_11_5.7z"; Break }
+ { $_ -ge "11.4" } { "https://github.com/sp-hash/TeamBlackMiner/releases/download/v1.61/TeamBlackMiner_1_62_cuda_11_4.7z"; Break }
+ Default { Return }
+}
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$Path = ".\Bin\$($Name)\TBMiner.exe"
+
+$DeviceSelector = @{ AMD = " --cl-devices"; NVIDIA = " --cuda-devices" }
+$DeviceEnumerator = @{ AMD = "Type_Vendor_Id"; NVIDIA = "Type_Vendor_Index" } # Device numeration seems to be mixed up with OpenCL
+
+$Algorithms = [PSCustomObject[]]@(
+ [PSCustomObject]@{ Algorithm = "EtcHash"; Type = "AMD"; Fee = 0.005; MinMemGB = ($Pools."EtcHash".DAGSize + 0.95GB) / 1GB; MinerSet = 0; Tuning = ""; WarmupTimes = @(45, 30); Arguments = " --algo etchash" } # PhoenixMiner-v6.1b may be faster, but I see lower speed at the pool
+ [PSCustomObject]@{ Algorithm = "Ethash"; Type = "AMD"; Fee = 0.005; MinMemGB = ($Pools."Ethash".DAGSize + 0.95GB) / 1GB; MinerSet = 0; Tuning = ""; WarmupTimes = @(45, 30); Arguments = " --algo ethash" } # PhoenixMiner-v6.1b may be faster, but I see lower speed at the pool
+ [PSCustomObject]@{ Algorithm = "EthashLowMem"; Type = "AMD"; Fee = 0.005; MinMemGB = ($Pools."EthashLowMem".DAGSize + 0.95GB) / 1GB; MinerSet = 1; Tuning = ""; WarmupTimes = @(45, 30); Arguments = " --algo ethash"} # TTMiner-v5.0.3 is fastest
+ # [PSCustomObject]@{ Algorithm = "VertHash"; Type = "AMD"; Fee = 0.01; MinMemGB = 4.0; MinerSet = 1; Tuning = " --tweak 2"; WarmupTimes = @(45, 180); Arguments = " --algo vertcoin" }
+
+ [PSCustomObject]@{ Algorithm = "EtcHash"; Type = "NVIDIA"; Fee = 0.005; MinMemGB = ($Pools."EtcHash".DAGSize + 0.95GB) / 1GB; MinerSet = 0; Tuning = " --tweak 2"; WarmupTimes = @(45, 30); Arguments = " --algo etchash" } # PhoenixMiner-v6.1b may be faster, but I see lower speed at the pool
+ [PSCustomObject]@{ Algorithm = "Ethash"; Type = "NVIDIA"; Fee = 0.005; MinMemGB = ($Pools."Ethash".DAGSize + 0.95GB) / 1GB; MinerSet = 0; Tuning = " --tweak 2"; WarmupTimes = @(45, 30); Arguments = " --algo ethash" } # PhoenixMiner-v6.1b may be faster, but I see lower speed at the pool
+ [PSCustomObject]@{ Algorithm = "EthashLowMem"; Type = "NVIDIA"; Fee = 0.005; MinMemGB = ($Pools."EthashLowMem".DAGSize + 0.95GB) / 1GB; MinerSet = 1; Tuning = " --tweak 2"; WarmupTimes = @(45, 30); Arguments = " --algo ethash" } # TTMiner-v5.0.3 is fastest
+ # [PSCustomObject]@{ Algorithm = "VertHash"; Type = "NVIDIA"; Fee = 0.01; MinMemGB = 4.0; MinerSet = 1; Tuning = " --tweak 2"; WarmupTimes = @(45, 180); Arguments = " --algo vertcoin" }
+)
+
+If ($Algorithms = $Algorithms | Where-Object MinerSet -LE $Config.MinerSet | Where-Object { $Pools.($_.Algorithm).Host }) {
+
+ $Devices | Where-Object Type -in @($Algorithms.Type) | Select-Object Type, Model -Unique | ForEach-Object {
+
+ $Miner_Devices = $Devices | Where-Object Type -EQ $_.Type | Where-Object Model -EQ $_.Model
+
+ $MinerAPIPort = [UInt16]($Config.APIPort + ($Miner_Devices | Sort-Object Id | Select-Object -First 1 -ExpandProperty Id) * 2 + 1)
+
+ $Algorithms | Where-Object Type -EQ $_.Type | ConvertTo-Json | ConvertFrom-Json | ForEach-Object {
+
+ If ($AvailableMiner_Devices = $Miner_Devices | Where-Object MemoryGB -ge $_.MinMemGB) {
+
+ $Miner_Name = (@($Name) + @($AvailableMiner_Devices.Model | Sort-Object -Unique | ForEach-Object { $Model = $_; "$(@($AvailableMiner_Devices | Where-Object Model -EQ $Model).Count)x$Model" }) | Select-Object) -join '-' -replace ' '
+
+ # Get arguments for available miner devices
+ # $_.Arguments = Get-ArgumentsPerDevice -Arguments $_.Arguments -ExcludeArguments @("algo", "cl-devices", "cuda-devices", "tweak") -DeviceIDs $AvailableMiner_Devices.$DeviceEnumerator
+
+ $_.Arguments += " --hostname $($Pools.($_.Algorithm).Host) --port $($Pools.($_.Algorithm).Port) --wallet $($Pools.($_.Algorithm).User -split '\.' | Select-Object -First 1) --worker-name $($Config.Workername)"
+ $_.Arguments += " --server-passwd $($Pools.($_.Algorithm).Pass)$(If ($Pools.($_.Algorithm).BaseName -eq "ProHashing" -and $_.Algorithm -eq "EthashLowMem") { ",l=$((($AvailableMiner_Devices.Memory | Measure-Object -Minimum).Minimum - 0.95GB) / 1GB)" })"
+
+ If ($Pools.($_.Algorithm).SSL) { $_.Arguments += " --ssl" }
+
+ # Apply tuning parameters
+ If ($Variables.UseMinerTweaks -eq $true) { $_.Arguments += $_.Tuning }
+
+ [PSCustomObject]@{
+ Name = $Miner_Name
+ DeviceName = $AvailableMiner_Devices.Name
+ Type = $AvailableMiner_Devices.Type
+ Path = $Path
+ Arguments = ("$($_.Arguments) --api --api-port $MinerAPIPort$($DeviceSelector.($_.Type)) [$(($AvailableMiner_Devices.($DeviceEnumerator.($_.Type)) | Sort-Object -Unique | ForEach-Object { '{0:x}' -f $_ }) -join ',')]" -replace "\s+", " ").trim()
+ Algorithm = $_.Algorithm
+ API = "TeamBlackMiner"
+ Port = $MinerAPIPort
+ URI = $Uri
+ Fee = $_.Fee
+ MinerUri = "http://localhost:$($MinerAPIPort)/threads"
+ WarmupTimes = $_.WarmupTimes # First value: seconds until miner must send first sample, if no sample is received miner will be marked as failed; Second value: seconds until miner sends stable hashrates that will count for benchmarking
+ }
+ }
+ }
+ }
+}
diff --git a/Miners/TeamRedMiner-v0.9.4.2.ps1 b/Miners/TeamRedMiner-v0.9.4.2.ps1
new file mode 100644
index 0000000000..01ef275629
--- /dev/null
+++ b/Miners/TeamRedMiner-v0.9.4.2.ps1
@@ -0,0 +1,115 @@
+using module ..\Includes\Include.psm1
+
+If (-not ($Devices = $Variables.EnabledDevices | Where-Object { $_.Type -eq "AMD" -and $_.OpenCL.ClVersion -ge "OpenCL C 2.0" })) { Return }
+
+$Uri = "https://github.com/Minerx117/miners/releases/download/TeamRedMiner/teamredminer-v0.9.4.2-win.zip"
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$Path = ".\Bin\$($Name)\teamredminer.exe"
+$DeviceEnumerator = "Type_Vendor_Slot"
+
+$Algorithms = [PSCustomObject[]]@(
+ [PSCustomObject]@{ Algorithm = @("Autolykos2"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=autolykos2" }
+ [PSCustomObject]@{ Algorithm = @("Chukwa"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=trtl_chukwa" }
+ [PSCustomObject]@{ Algorithm = @("Chukwa2"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=trtl_chukwa2" }
+ [PSCustomObject]@{ Algorithm = @("CryptonightCcx"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=cn_conceal --auto_tune=QUICK --auto_tune_runs=2 --allow_large_alloc --no_lean --rig_id=$($Config.WorkerName)" } # SRBMinerMulti-v0.9.4 is fastest
+ [PSCustomObject]@{ Algorithm = @("CryptonightHeavy"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=cn_heavy --auto_tune=QUICK --auto_tune_runs=2 --allow_large_alloc --no_lean --rig_id=$($Config.WorkerName)" }
+ [PSCustomObject]@{ Algorithm = @("CryptonightHaven"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=cn_haven --auto_tune=QUICK --auto_tune_runs=2 --allow_large_alloc --no_lean --rig_id=$($Config.WorkerName)" }
+ [PSCustomObject]@{ Algorithm = @("CryptonightHeavyTube"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=cn_saber --auto_tune=QUICK --auto_tune_runs=2 --allow_large_alloc --no_lean --rig_id=$($Config.WorkerName)" }
+ # [PSCustomObject]@{ Algorithm = @("CryptonightR"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 1; WarmupTimes = @(60, 15); Arguments = " --algo=cnr --auto_tune=QUICK --auto_tune_runs=2 --allow_large_alloc --no_lean --rig_id=$($Config.WorkerName)" } # Not profitable at all
+ [PSCustomObject]@{ Algorithm = @("CryptonightV1"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=cnv8 --auto_tune=QUICK --auto_tune_runs=2 --allow_large_alloc --no_lean --rig_id=$($Config.WorkerName)" }
+ [PSCustomObject]@{ Algorithm = @("CryptonightDouble"); Fee = @(0.025); MinMemGB = 4.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=cnv8_dbl --auto_tune=QUICK --auto_tune_runs=2 --allow_large_alloc --no_lean --rig_id=$($Config.WorkerName)" } # XmRig-v6.17.0 is fastest
+ [PSCustomObject]@{ Algorithm = @("CryptonightHalf"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=cnv8_half --auto_tune=QUICK --auto_tune_runs=2 --allow_large_alloc --no_lean --rig_id=$($Config.WorkerName)" }
+ [PSCustomObject]@{ Algorithm = @("CryptonightTurtle"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=cnv8_trtl --auto_tune=QUICK --auto_tune_runs=2 --allow_large_alloc --no_lean --rig_id=$($Config.WorkerName)" }
+ [PSCustomObject]@{ Algorithm = @("CryptonightRwz"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=cnv8_rwz --auto_tune=QUICK --auto_tune_runs=2 --allow_large_alloc --no_lean --rig_id=$($Config.WorkerName)" }
+ [PSCustomObject]@{ Algorithm = @("CryptonightUpx"); Fee = @(0.025); MinMemGB = 3.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=cnv8_upx2 --auto_tune=QUICK --auto_tune_runs=2 --allow_large_alloc --no_lean --rig_id=$($Config.WorkerName)" }
+ [PSCustomObject]@{ Algorithm = @("CuckarooD29"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=cuckarood29_grin" } # 2GB is not enough
+ [PSCustomObject]@{ Algorithm = @("Cuckatoo31"); Fee = @(0.025); MinMemGB = 3.0; MinerSet = 1; WarmupTimes = @(60, 15); Arguments = " --algo=cuckatoo31_grin" } # lolMiner-v1.48 is fastest
+ [PSCustomObject]@{ Algorithm = @("EtcHash"); Fee = @(0.01); MinMemGB = ($Pools."EtcHash".DAGSize + 0.95GB) / 1GB; MinerSet = 1; WarmupTimes = @(45, 75); Arguments = " --algo=etchash" } # PhoenixMiner-v6.1b is fastest
+ [PSCustomObject]@{ Algorithm = @("Ethash"); Fee = @(0.01); MinMemGB = ($Pools."Ethash".DAGSize + 0.95GB) / 1GB; MinerSet = 1; WarmupTimes = @(45, 75); Arguments = " --algo=ethash" } # PhoenixMiner-v6.1b is fastest
+ [PSCustomObject]@{ Algorithm = @("Ethash", "SHA256ton"); Fee = @(0.01); MinMemGB = ($Pools."Ethash".DAGSize + 0.95GB) / 1GB; MinerSet = 0; WarmupTimes = @(45, 90); Arguments = " --algo=ethash" }
+ [PSCustomObject]@{ Algorithm = @("EthashLowMem"); Fee = @(0.01); MinMemGB = ($Pools."EthashLowMem".DAGSize + 0.95GB) / 1GB; MinerSet = 1; WarmupTimes = @(45, 75); Arguments = " --algo=ethash" }
+ [PSCustomObject]@{ Algorithm = @("FiroPoW"); Fee = @(0.02); MinMemGB = 3.0; MinerSet = 0; WarmupTimes = @(45, 75); Arguments = " --algo=firopow" } # Wildrig-v0.31.3 is fastest on Polaris
+ [PSCustomObject]@{ Algorithm = @("KawPoW"); Fee = @(0.02); MinMemGB = ($Pools."KawPoW".DAGSize + 0.95GB) / 1GB; MinerSet = 0; WarmupTimes = @(60, 75); Arguments = " --algo=kawpow" } # Wildrig-v0.31.3 is fastest on Polaris
+ [PSCustomObject]@{ Algorithm = @("Lyra2z"); Fee = @(0.03); MinMemGB = 2.0; MinerSet = 1; WarmupTimes = @(60, 15); Arguments = " --algo=lyra2z" } # XmRig-v6.17.0 is faster
+ [PSCustomObject]@{ Algorithm = @("Lyra2RE3"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=lyra2rev3" }
+ [PSCustomObject]@{ Algorithm = @("MTP"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(45, 45); Arguments = " --algo=mtp" }
+ [PSCustomObject]@{ Algorithm = @("Nimiq"); Fee = @(0.025); MinMemGB = 4.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=nimiq --nimiq_worker=$($Config.Workername)" }
+ [PSCustomObject]@{ Algorithm = @("Phi2"); Fee = @(0.03); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=phi2" }
+ [PSCustomObject]@{ Algorithm = @("SHA256ton"); Fee = @(0.01); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=ton" }
+ [PSCustomObject]@{ Algorithm = @("VertHash"); Fee = @(0.025); MinMemGB = 4.0; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --algo=verthash --verthash_file=..\..\Cache\VertHash.dat" }
+ [PSCustomObject]@{ Algorithm = @("X16r"); Fee = @(0.025); MinMemGB = 4.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=x16r" }
+ [PSCustomObject]@{ Algorithm = @("X16rv2"); Fee = @(0.025); MinMemGB = 4.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=x16rv2" }
+ [PSCustomObject]@{ Algorithm = @("X16s"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=x16s" }
+ [PSCustomObject]@{ Algorithm = @("X16rt"); Fee = @(0.025); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo=x16rt" }
+)
+
+If ($Algorithms = $Algorithms | Where-Object MinerSet -LE $Config.MinerSet | Where-Object { $Pools.($_.Algorithm[0]).Host -and (-not $_.Algorithm[1] -or $PoolsSecondaryAlgorithm.($_.Algorithm[1]).Host) }) {
+
+ $Devices | Select-Object Model -Unique | ForEach-Object {
+
+ $Miner_Devices = $Devices | Where-Object Model -EQ $_.Model
+
+ $MinerAPIPort = [UInt16]($Config.APIPort + ($Miner_Devices | Sort-Object Id | Select-Object -First 1 -ExpandProperty Id) * 2 + 1)
+
+ $Algorithms | ConvertTo-Json | ConvertFrom-Json | ForEach-Object {
+
+ $AvailableMiner_Devices = $Miner_Devices | Where-Object MemoryGB -ge $_.MinMemGB
+
+ If ($_.Algorithm -notin @("Autolykos2", "EtcHash", "Ethash", "Kawpow", "Nimiq", "MTP", "VertHash")) { $AvailableMiner_Devices = $AvailableMiner_Devices | Where-Object { $_.Model -notmatch "^Radeon RX 5[0-9]{3}.*" } } # Navi is not supported by other algorithms
+
+ If ($AvailableMiner_Devices) {
+
+ $Miner_Name = (@($Name) + @($AvailableMiner_Devices.Model | Sort-Object -Unique | ForEach-Object { $Model = $_; "$(@($AvailableMiner_Devices | Where-Object Model -EQ $Model).Count)x$Model" }) + @(If ($_.Algorithm[1]) { "$($_.Algorithm[0])&$($_.Algorithm[1])" }) + @($_.Intensity) | Select-Object) -join '-' -replace ' '
+
+ # Get arguments for available miner devices
+ # $_.Arguments = Get-ArgumentsPerDevice -Arguments $_.Arguments -ExcludeArguments @("algo", "autotune", "rig_id") -DeviceIDs $AvailableMiner_Devices.$DeviceEnumerator
+
+ If ($_.Algorithm -eq "VertHash") {
+ If (-not (Test-Path -Path ".\Cache\VertHash.dat" -PathType Leaf )) {
+ If (-not (Test-Path -Path ".\Cache" -PathType Container)) { New-Item -Path . -Name "Cache" -ItemType Directory | Out-Null }
+ $WarmupTime[1] += 45 # Seconds, max. wait time until first data sample, allow extra time to build verthash.dat
+ }
+ }
+
+ If ($_.Algorithm[0] -eq "SHA256ton") {
+ If ($Pools.($_.Algorithm[0]).BaseName -eq "TonWhales") {
+ $_.Arguments += " --url=stratum+tcp://tcp.$($Pools.($_.Algorithm[0]).Host):$($Pools.($_.Algorithm[0]).Port)"
+ }
+ Else {
+ $_.Arguments += " --url=stratum+tcp://$($Pools.($_.Algorithm[0]).Host):$($Pools.($_.Algorithm[0]).Port)"
+ }
+ }
+ Else {
+ $_.Arguments += " --url=$(If ($Pools.($_.Algorithm[0]).SSL) { "stratum+ssl" } Else { "stratum+tcp" })://$($Pools.($_.Algorithm[0]).Host):$($Pools.($_.Algorithm[0]).Port)"
+ If ($Pools.($_.Algorithm[0]).DAGsize -ne $null -and $Pools.($_.Algorithm[0]).BaseName -in @("MiningPoolHub", "NiceHash")) { $_.Arguments += " --eth_stratum_mode=nicehash" }
+
+ If ($_.Algorithm[0] -match "^Et(c)hash.+" -and $AvailableMiner_Devices.Model -notmatch "^Radeon RX [0-9]{3} ") { $_.Fee = @(0.0075) } # Polaris cards 0.75%
+ }
+ $_.Arguments += " --user=$($Pools.($_.Algorithm[0]).User) --pass=$($Pools.($_.Algorithm[0]).Pass)$(If ($Pools.($_.Algorithm[0]).BaseName -eq "ProHashing" -and $_.Algorithm -eq "EthashLowMem") { ",l=$((($AvailableMiner_Devices.Memory | Measure-Object -Minimum).Minimum - 0.95GB) / 1GB)" })"
+
+ If ($_.Algorithm[1] -eq "SHA256ton") {
+ If ($Pools.($_.Algorithm[1]).BaseName -eq "TonWhales") {
+ $_.Arguments += " --ton_start --url=stratum+tcp://tcp.$($Pools.($_.Algorithm[1]).Host):$($Pools.($_.Algorithm[1]).Port) --user=$($Pools.($_.Algorithm[1]).User) --pass=$($Pools.($_.Algorithm[1]).pass) --api2_listen=127.0.0.1:$($MinerAPIPort + 1) --ton_end"
+ }
+ Else {
+ $_.Arguments += " --ton_start --url=stratum+tcp://$($Pools.($_.Algorithm[1]).Host):$($Pools.($_.Algorithm[1]).Port) --user=$($Pools.($_.Algorithm[1]).User) --pass=$($Pools.($_.Algorithm[1]).pass) --api2_listen=127.0.0.1:$($MinerAPIPort + 1) --ton_end"
+ }
+ }
+
+ [PSCustomObject]@{
+ Name = $Miner_Name
+ DeviceName = $AvailableMiner_Devices.Name
+ Type = $AvailableMiner_Devices.Type
+ Path = $Path
+ Arguments = ("$($_.Arguments) --watchdog_script --no_gpu_monitor --init_style=3 --hardware=gpu --platform=$($AvailableMiner_Devices.PlatformId | Sort-Object -Unique) --api_listen=127.0.0.1:$MinerAPIPort --devices=$(($AvailableMiner_Devices.$DeviceEnumerator | Sort-Object -Unique | ForEach-Object { '{0:d}' -f $_ }) -join ',')" -replace "\s+", " ").trim()
+ Algorithm = ($_.Algorithm[0], $_.Algorithm[1]) | Select-Object
+ API = "Xgminer"
+ Port = $MinerAPIPort
+ URI = $Uri
+ Fee = $_.Fee
+ WarmupTimes = $_.WarmupTimes # First value: seconds until miner must send first sample, if no sample is received miner will be marked as failed; Second value: seconds until miner sends stable hashrates that will count for benchmarking
+ }
+ }
+ }
+ }
+}
diff --git a/Miners/Trex-v0.25.12.ps1 b/Miners/Trex-v0.25.12.ps1
new file mode 100644
index 0000000000..2f0d743593
--- /dev/null
+++ b/Miners/Trex-v0.25.12.ps1
@@ -0,0 +1,98 @@
+using module ..\Includes\Include.psm1
+
+If (-not ($Devices = $Variables.EnabledDevices | Where-Object Type -EQ "NVIDIA")) { Return }
+
+$Uri = "https://github.com/trexminer/T-Rex/releases/download/0.25.12/t-rex-0.25.12-win.zip"
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$Path = ".\Bin\$($Name)\t-rex.exe"
+$DeviceEnumerator = "Type_Vendor_Index"
+
+$Algorithms = [PSCustomObject[]]@(
+ [PSCustomObject]@{ Algorithm = @("Autolykos2"); Fee = @(0.02); MinMemGB = 3; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(45, 30); Arguments = " --algo autolykos2 --intensity 25" }
+ [PSCustomObject]@{ Algorithm = @("Blake3"); Fee = @(0.01); MinMemGB = 2; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(45, 0); Arguments = " --algo blake3 --intensity 25" }
+ [PSCustomObject]@{ Algorithm = @("EtcHash"); Fee = @(0.01); MinMemGB = ($Pools."EtcHash".DAGSize + 0.95GB) / 1GB; MinerSet = 1; Tuning = " --mt 3"; WarmupTimes = @(60, 15); Arguments = " --algo etchash --intensity 25" } # GMiner-v2.91 is fastest
+ [PSCustomObject]@{ Algorithm = @("Ethash"); Fee = @(0.01); MinMemGB = ($Pools."Ethash".DAGSize + 0.95GB) / 1GB; MinerSet = 1; Tuning = " --mt 3"; WarmupTimes = @(60, 15); Arguments = " --algo ethash --intensity 25" } # GMiner-v2.91 is fastest
+ [PSCustomObject]@{ Algorithm = @("Ethash", "Autolykos2"); Fee = @(0.01, 0.02); MinMemGB = 8; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(60, 15); Arguments = " --algo ethash --dual-algo autolykos2 --lhr-tune -1 --lhr-autotune-interval 1" }
+ [PSCustomObject]@{ Algorithm = @("Ethash", "Blake3"); Fee = @(0.01, 0.01); MinMemGB = ($Pools."EtHash".DAGSize + 0.95GB) / 1GB; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(60, 15); Arguments = " --algo ethash --dual-algo blake3 --lhr-tune -1 --lhr-autotune-interval 1" }
+ [PSCustomObject]@{ Algorithm = @("Ethash", "FiroPoW"); Fee = @(0.01, 0.01); MinMemGB = 10; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(255, 15); Arguments = " --algo ethash --dual-algo firopow --lhr-tune -1" }
+ [PSCustomObject]@{ Algorithm = @("Ethash", "KawPoW"); Fee = @(0.01, 0.01); MinMemGB = 10; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(255, 15); Arguments = " --algo ethash --dual-algo kawpow --lhr-tune -1" }
+ [PSCustomObject]@{ Algorithm = @("Ethash", "Octopus"); Fee = @(0.01, 0.02); MinMemGB = 8; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(60, 15); Arguments = " --algo ethash --dual-algo octopus --lhr-tune -1" }
+ [PSCustomObject]@{ Algorithm = @("EthashLowMem"); Fee = @(0.01); MinMemGB = ($Pools."EthashLowMem".DAGSize + 0.95GB) / 1GB; MinerSet = 1; Tuning = " --mt 3"; WarmupTimes = @(60, 15); Arguments = " --algo ethash --intensity 25" } # TTMiner-v5.0.3 is fastest
+ [PSCustomObject]@{ Algorithm = @("FiroPoW"); Fee = @(0.01); MinMemGB = 5; MinerSet = 1; Tuning = " --mt 3"; WarmupTimes = @(60, 15); Arguments = " --algo firopow --intensity 25" }
+ [PSCustomObject]@{ Algorithm = @("KawPoW"); Fee = @(0.01); MinMemGB = ($Pools."KawPoW".DAGSize + 0.95GB) / 1GB; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(45, 0); Arguments = " --algo kawpow --intensity 25" } # XmRig-v6.17.0 is almost as fast but has no fee
+ [PSCustomObject]@{ Algorithm = @("MTP"); Fee = @(0.01); MinMemGB = 3; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(30, 15); Arguments = " --algo mtp --intensity 21" }
+ [PSCustomObject]@{ Algorithm = @("MTPTcr"); Fee = @(0.01); MinMemGB = 3; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(30, 15); Arguments = " --algo mtp-tcr --intensity 21" }
+ [PSCustomObject]@{ Algorithm = @("Multi"); Fee = @(0.01); MinMemGB = 2; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(30, 0); Arguments = " --algo multi --intensity 25" }
+ [PSCustomObject]@{ Algorithm = @("Octopus"); Fee = @(0.02); MinMemGB = 6.1; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(60, 15); Arguments = " --algo octopus" } # 6GB is not enough
+ [PSCustomObject]@{ Algorithm = @("ProgPoW"); Fee = @(0.01); MinMemGB = ($Pools."ProgPoW".DAGSize + 0.95GB) / 1GB; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(30, 0); Arguments = " --algo progpow" }
+ [PSCustomObject]@{ Algorithm = @("Tensority"); Fee = @(0.01); MinMemGB = 2; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(30, 0); Arguments = " --algo tensority --intensity 25" }
+ [PSCustomObject]@{ Algorithm = @("Veil"); Fee = @(0.01); MinMemGB = 2; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(30, 0); Arguments = " --algo progpow-veil --intensity 24" }
+ [PSCustomObject]@{ Algorithm = @("VeriBlock"); Fee = @(0.01); MinMemGB = 2; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(30, 0); Arguments = " --algo progpow-veriblock" }
+ [PSCustomObject]@{ Algorithm = @("Zano"); Fee = @(0.01); MinMemGB = 2; MinerSet = 0; Tuning = " --mt 3"; WarmupTimes = @(30, 0); Arguments = " --algo progpowz --intensity 25" }
+)
+
+If ($Algorithms = $Algorithms | Where-Object MinerSet -LE $Config.MinerSet | Where-Object { $Pools.($_.Algorithm[0]).Host -and (-not $_.Algorithm[1] -or $PoolsSecondaryAlgorithm.($_.Algorithm[1]).Host) }) {
+
+ $Devices | Select-Object Model -Unique | ForEach-Object {
+
+ $Miner_Devices = $Devices | Where-Object Model -EQ $_.Model
+
+ $MinerAPIPort = [UInt16]($Config.APIPort + ($Miner_Devices | Sort-Object Id | Select-Object -First 1 -ExpandProperty Id) * 2 + 1)
+
+ $Algorithms | ConvertTo-Json | ConvertFrom-Json | ForEach-Object {
+
+ If ($AvailableMiner_Devices = $Miner_Devices | Where-Object MemoryGB -ge $_.MinMemGB) {
+
+ $Miner_Name = (@($Name) + @($AvailableMiner_Devices.Model | Sort-Object -Unique | ForEach-Object { $Model = $_; "$(@($AvailableMiner_Devices | Where-Object Model -EQ $Model).Count)x$Model" }) + @(If ($_.Algorithm[1]) { "$($_.Algorithm[0])&$($_.Algorithm[1])" }) | Select-Object) -join '-' -replace ' '
+
+ If ($AvailableMiner_Devices | Where-Object MemoryGB -le 2) { $_.Arguments = $_.Arguments -replace " --intensity [0-9\.]+" }
+
+ # Get arguments for available miner devices
+ # $_.Arguments = Get-ArgumentsPerDevice -Arguments $_.Arguments -ExcludeArguments @("algo", "dual-algo") -DeviceIDs $AvailableMiner_Devices.$DeviceEnumerator
+
+ $_.Arguments += " --url $(If ($Pools.($_.Algorithm[0]).DAGsize -ne $null -and $Pools.($_.Algorithm[0]).BaseName -in @("MiningPoolHub", "NiceHash", "ProHashing")) { "stratum2" } Else { "stratum" })$(If ($Pools.($_.Algorithm[0]).SSLe) { "+ssl://" } Else { "+tcp://" })$($Pools.($_.Algorithm[0]).Host):$($Pools.($_.Algorithm[0]).Port)"
+ #(ethash, kawpow, progpow) Worker name is not being passed for some mining pools
+ # From now on the username (--user) for these algorithms is no longer parsed as .
+ $_.Arguments += " --user $(If ($Pools.($_.Algorithm[0]).DAGsize -gt 0 -and ($Pools.($_.Algorithm[0]).User -split "\.").Count -eq 2 -and $Pools.($_.Algorithm[0]).BaseName -ne "MiningPoolHub") { "$($Pools.($_.Algorithm[0]).User -split "\." | Select-Object -First 1) --worker $($Pools.($_.Algorithm[0]).User -split "\." | Select-Object -Index 1)" } Else { "$($Pools.($_.Algorithm[0]).User)" })"
+ $_.Arguments += " --pass $($Pools.($_.Algorithm[0]).Pass)$(If ($Pools.($_.Algorithm[0]).BaseName -eq "ProHashing" -and $_.Algorithm -eq "EthashLowMem") { ",l=$((($AvailableMiner_Devices.Memory | Measure-Object -Minimum).Minimum - 0.95GB) / 1GB)" })"
+
+ If ($_.Algorithm[0] -in @("ProgPoW", "Zano")) {
+ If ($Pools.($_.Algorithm[0]).Currency -in @("SERO", "ZANO")) {
+ $_.Arguments += " --coin $($Pools.($_.Algorithm[0]).Currency)"
+ }
+ Else {
+ Return
+ }
+ }
+
+ If ($_.Algorithm[1]) {
+ $_.Arguments += " --url2 $(If ($Pools.($_.Algorithm[1]).DAGsize -ne $null -and $Pools.($_.Algorithm[1]).BaseName -in @("MiningPoolHub", "NiceHash", "ProHashing")) { "stratum2" } Else { "stratum" })$(If ($Pools.($_.Algorithm[1]).SSLe) { "+ssl://" } Else { "+tcp://" })$($Pools.($_.Algorithm[1]).Host):$($Pools.($_.Algorithm[1]).Port)"
+ #(ethash, kawpow, progpow) Worker name is not being passed for some mining pools
+ # From now on the username (--user) for these algorithms is no longer parsed as .
+ $_.Arguments += " --user2 $(If ($Pools.($_.Algorithm[1]).DAGsize -gt 0 -and ($Pools.($_.Algorithm[1]).User -split "\.").Count -eq 2 -and $Pools.($_.Algorithm[1]).BaseName -ne "MiningPoolHub") { "$($Pools.($_.Algorithm[1]).User -split "\." | Select-Object -First 1) --worker2 $($Pools.($_.Algorithm[1]).User -split "\." | Select-Object -Index 1)" } Else { "$($Pools.($_.Algorithm[1]).User)" })"
+ $_.Arguments += " --pass2 $($Pools.($_.Algorithm[1]).Pass)$(If ($Pools.($_.Algorithm[1]).BaseName -eq "ProHashing" -and $_.Algorithm -eq "EthashLowMem") { ",l=$((($AvailableMiner_Devices.Memory | Measure-Object -Minimum).Minimum - 0.95GB) / 1GB)" })"
+ }
+
+ # Apply tuning parameters
+ If ($Variables.UseMinerTweaks -eq $true) { $_.Arguments += $_.Tuning }
+
+ If ($_.Arguments -notmatch "--kernel [0-9]") { $_.WarmupTimes[0] += 15 } # Allow extra seconds for kernel auto tuning
+
+ [PSCustomObject]@{
+ Name = $Miner_Name
+ DeviceName = $AvailableMiner_Devices.Name
+ Type = $AvailableMiner_Devices.Type
+ Path = $Path
+ Arguments = ("$($_.Arguments) --no-strict-ssl --no-watchdog --gpu-report-interval 5 --quiet --retry-pause 1 --timeout 50000 --api-bind-http 127.0.0.1:$($MinerAPIPort) --api-read-only --devices $(($AvailableMiner_Devices.$DeviceEnumerator | Sort-Object -Unique | ForEach-Object { '{0:x}' -f $_ }) -join ',')" -replace "\s+", " ").trim()
+ Algorithm = ($_.Algorithm[0], $_.Algorithm[1]) | Select-Object
+ API = "Trex"
+ Port = $MinerAPIPort
+ URI = $Uri
+ Fee = $_.Fee # Dev fee
+ MinerUri = "http://localhost:$($MinerAPIPort)/trex"
+ WarmupTimes = $_.WarmupTimes # First value: seconds until miner must send first sample, if no sample is received miner will be marked as failed; Second value: seconds until miner sends stable hashrates that will count for benchmarking
+ }
+ }
+ }
+ }
+}
diff --git a/Miners/VertHashMiner-v0.7.2.ps1 b/Miners/VertHashMiner-v0.7.2.ps1
new file mode 100644
index 0000000000..18aaf6a73a
--- /dev/null
+++ b/Miners/VertHashMiner-v0.7.2.ps1
@@ -0,0 +1,61 @@
+using module ..\Includes\Include.psm1
+
+If (-not ($Devices = $Variables.EnabledDevices | Where-Object { ($_.Type -eq "AMD" -and $_.OpenCL.ClVersion -ge "OpenCL C 1.2") -or ($_.Type -eq "NVIDIA" -and $_.OpenCl.ComputeCapability -ge "3.0") })) { Return }
+
+$Uri = "https://github.com/Minerx117/miners/releases/download/VertHashMiner/VertHashMiner_0.7.2.zip"
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$Path = ".\Bin\$($Name)\verthashminer.exe"
+
+$DeviceEnumerator = "Type_Vendor_Index"
+
+$Algorithms = [PSCustomObject[]]@(
+ [PSCustomObject]@{ Algorithm = "VertHash"; MinMemGB = 2; Type = "AMD"; MinerSet = 0; WarmupTimes = @(30, 0); Arguments = " --cl-devices" }
+ [PSCustomObject]@{ Algorithm = "VertHash"; MinMemGB = 2; Type = "NVIDIA"; MinerSet = 0; WarmupTimes = @(30, 0); Arguments = " --cu-devices" }
+)
+
+If ($Algorithms = $Algorithms | Where-Object MinerSet -LE $Config.MinerSet | Where-Object { $Pools.($_.Algorithm).Host }) {
+
+ $Devices | Where-Object Type -in @($Algorithms.Type) | Select-Object Type, Model -Unique | ForEach-Object {
+
+ $Miner_Devices = $Devices | Where-Object Type -EQ $_.Type | Where-Object Model -EQ $_.Model
+
+ $MinerAPIPort = 0 # Miner has no API
+
+ $Algorithms | Where-Object Type -EQ $_.Type | ConvertTo-Json | ConvertFrom-Json | ForEach-Object {
+
+ If ($AvailableMiner_Devices = $Miner_Devices | Where-Object MemoryGB -ge $_.MinMemGB) {
+
+ $Miner_Name = (@($Name) + @($AvailableMiner_Devices.Model | Sort-Object -Unique | ForEach-Object { $Model = $_; "$(@($AvailableMiner_Devices | Where-Object Model -EQ $Model).Count)x$Model" }) | Select-Object) -join '-' -replace ' '
+
+ $_.Arguments += " $(($AvailableMiner_Devices.$DeviceEnumerator | Sort-Object -Unique | ForEach-Object { '{0:x}' -f $_ }) -join ',')"
+
+ # Get arguments for available miner devices
+ # $_.Arguments = Get-ArgumentsPerDevice -Arguments $_.Arguments -ExcludeArguments @("algo") -DeviceIDs $AvailableMiner_Devices.$DeviceEnumerator
+
+ If ($_.Algorithm -eq "VertHash") {
+ If (Test-Path -Path ".\Cache\VertHash.dat" -PathType Leaf) {
+ $_.Arguments += " --verthash-data ..\..\Cache\VertHash.dat"
+ }
+ Else {
+ $_.Arguments += " --gen-verthash-data ..\..\Cache\VertHash.dat"
+ $_.WarmupTimes[0] += 600; $_.WarmupTimes[0] += 600 # Seconds, max. wait time until first data sample, allow extra time to build verthash.dat
+ }
+ }
+
+ [PSCustomObject]@{
+ Name = $Miner_Name
+ DeviceName = $AvailableMiner_Devices.Name
+ Type = $AvailableMiner_Devices.Type
+ Path = $Path
+ Arguments = ("$($_.Arguments) --url stratum+tcp://$($Pools.($_.Algorithm).Host):$($Pools.($_.Algorithm).Port) --user $($Pools.($_.Algorithm).User) --pass $($Pools.($_.Algorithm).Pass)" -replace "\s+", " ").trim()
+ Algorithm = $_.Algorithm
+ API = "NoAPI"
+ Port = $MinerAPIPort
+ URI = $Uri
+ Fee = 0.01
+ WarmupTimes = $_.WarmupTimes # First value: seconds until miner must send first sample, if no sample is received miner will be marked as failed; Second value: seconds until miner sends stable hashrates that will count for benchmarking
+ }
+ }
+ }
+ }
+}
diff --git a/Miners/Wildrig-v0.31.3.ps1 b/Miners/Wildrig-v0.31.3.ps1
new file mode 100644
index 0000000000..7f7e480cdc
--- /dev/null
+++ b/Miners/Wildrig-v0.31.3.ps1
@@ -0,0 +1,151 @@
+using module ..\Includes\Include.psm1
+
+If (-not ($Devices = $Variables.EnabledDevices | Where-Object { ($_.Type -eq "AMD" -and $_.OpenCL.ClVersion -ge "OpenCL C 1.2") -or $_.Type -eq "NVIDIA"})) { Return }
+
+$Uri = "https://github.com/andru-kun/wildrig-multi/releases/download/0.31.3/wildrig-multi-windows-0.31.3.7z"
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$Path = ".\Bin\$($Name)\wildrig.exe"
+$DeviceEnumerator = "Type_Vendor_Slot"
+
+$Algorithms = [PSCustomObject[]]@(
+ [PSCustomObject]@{ Algorithm = "0x10"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 30); Arguments = " --algo 0x10" }
+ [PSCustomObject]@{ Algorithm = "AstralHash"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo glt-astralhash" }
+ [PSCustomObject]@{ Algorithm = "BCD"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo bcd" }
+ [PSCustomObject]@{ Algorithm = "Blake2bBtcc"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo blake2b-btcc" }
+ [PSCustomObject]@{ Algorithm = "Blake2bGlt"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo blake2b-glt" }
+ [PSCustomObject]@{ Algorithm = "Bmw512"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(60, 15); Arguments = " --algo bmw512" } # CcminerBmw512-v2.2.5 is fastest
+ [PSCustomObject]@{ Algorithm = "Bitcore"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo bitcore" }
+ [PSCustomObject]@{ Algorithm = "C11"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo c11" }
+ [PSCustomObject]@{ Algorithm = "Dedal"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo dedal" } # CryptoDredge-v0.26.0 is fastest
+ [PSCustomObject]@{ Algorithm = "Exosis"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo exosis" }
+ [PSCustomObject]@{ Algorithm = "Geek"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo geek" }
+ [PSCustomObject]@{ Algorithm = "Ghostrider"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo ghostrider" }
+ [PSCustomObject]@{ Algorithm = "GlobalHash"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo glt-globalhash" }
+ [PSCustomObject]@{ Algorithm = "HeavyHash"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo heavyhash" }
+ [PSCustomObject]@{ Algorithm = "Hex"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo hex" }
+ [PSCustomObject]@{ Algorithm = "Hmq1725"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo hmq1725" } # CryptoDredge-v0.26.0 is fastest
+ # [PSCustomObject]@{ Algorithm = "Honeycomb"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo honeycomb" } # Algo broken, last working version is 0.17.6
+ [PSCustomObject]@{ Algorithm = "JeongHash"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo glt-jeonghash" }
+ [PSCustomObject]@{ Algorithm = "KawPoW"; Type = "AMD"; Fee = @(0.01); MinMemGB = ($Pools."KawPoW".DAGSize + 0.95GB) / 1GB;; MinerSet = 1; WarmupTimes = @(45, 0); Arguments = " --algo kawpow" } # TeamRedMiner-v0.9.4.2 is fastest on Navi
+ [PSCustomObject]@{ Algorithm = "Lyra2RE3"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo lyra2v3" } # TeamRedMiner-v0.9.4.2 is fastest
+ [PSCustomObject]@{ Algorithm = "Lyra2TDC"; Type = "AMD"; Fee = @(0.02); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo lyra2tdc" }
+ [PSCustomObject]@{ Algorithm = "MegaBtx"; Type = "AMD"; Fee = @(0.02); MinMemGB = 1; MinerSet = 0; WarmupTimes = @(45, 15); Arguments = " --algo megabtx" }
+ [PSCustomObject]@{ Algorithm = "MegaMec"; Type = "AMD"; Fee = @(0.01); MinMemGB = 1; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo megamec" }
+ [PSCustomObject]@{ Algorithm = "Minotaur"; Type = "AMD"; Fee = @(0.05); MinMemGB = 1; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo minotaur" }
+ [PSCustomObject]@{ Algorithm = "MTP"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo mtp" } # TeamRedMiner-v0.9.4.2 is fastest
+ [PSCustomObject]@{ Algorithm = "MTPTrc"; Type = "AMD"; Fee = @(0.01); MinMemGB = 3; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo mtp-trc" }
+ [PSCustomObject]@{ Algorithm = "PadiHash"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo glt-padihash" }
+ [PSCustomObject]@{ Algorithm = "PawelHash"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo glt-pawelhash" }
+ [PSCustomObject]@{ Algorithm = "Phi"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo phi" }
+ [PSCustomObject]@{ Algorithm = "Phi5"; Type = "AMD"; Fee = @(0.02); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo phi5" }
+ [PSCustomObject]@{ Algorithm = "Polytimos"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo polytimos" }
+ [PSCustomObject]@{ Algorithm = "Sha256csm"; Type = "AMD"; Fee = @(0.02); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo sha256csm" }
+ [PSCustomObject]@{ Algorithm = "Sha256t"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo sha256t" }
+ [PSCustomObject]@{ Algorithm = "Sha256q"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo sha256q" }
+ [PSCustomObject]@{ Algorithm = "Renesis"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo renesis" }
+ [PSCustomObject]@{ Algorithm = "Skein2"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo skein2" }
+ [PSCustomObject]@{ Algorithm = "SkunkHash"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo skunkhash" }
+ [PSCustomObject]@{ Algorithm = "Sonoa"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo sonoa" }
+ [PSCustomObject]@{ Algorithm = "Timetravel"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo timetravel" }
+ [PSCustomObject]@{ Algorithm = "Tribus"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo tribus" }
+ [PSCustomObject]@{ Algorithm = "X11k"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo x11k" }
+ [PSCustomObject]@{ Algorithm = "X16r"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo x16r" } # TeamRedMiner-v0.9.4.2 is fastest
+ [PSCustomObject]@{ Algorithm = "X16rt"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo x16rt" }
+ [PSCustomObject]@{ Algorithm = "X16rv2"; Type = "AMD"; Fee = @(0.01); MinMemGB = 3; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo x16rv2" }
+ [PSCustomObject]@{ Algorithm = "X16s"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo x16s" }
+ [PSCustomObject]@{ Algorithm = "X17"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo x17" }
+ [PSCustomObject]@{ Algorithm = "X17r"; Type = "AMD"; Fee = @(0.02); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo x17r --protocol ufo2" }
+ [PSCustomObject]@{ Algorithm = "X21s"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo x21s" } # TeamRedMiner-v0.9.4.2 is fastest
+ # [PSCustomObject]@{ Algorithm = "X22i"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo x22i" } # No results
+ [PSCustomObject]@{ Algorithm = "X33"; Type = "AMD"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo x33" }
+ [PSCustomObject]@{ Algorithm = "WildKeccak"; Type = "AMD"; Fee = @(0.02); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo wildkeccak" }
+
+ [PSCustomObject]@{ Algorithm = "0x10"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo 0x10" }
+ [PSCustomObject]@{ Algorithm = "AstralHash"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo glt-astralhash" }
+ [PSCustomObject]@{ Algorithm = "BCD"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo bcd" }
+ [PSCustomObject]@{ Algorithm = "Blake2bBtcc"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo blake2b-btcc" }
+ [PSCustomObject]@{ Algorithm = "Blake2bGlt"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo blake2b-glt" }
+ [PSCustomObject]@{ Algorithm = "Bmw512"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(60, 15); Arguments = " --algo bmw512" } # CcminerBmw512-v2.2.5 is fastest
+ [PSCustomObject]@{ Algorithm = "Bitcore"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo bitcore" }
+ [PSCustomObject]@{ Algorithm = "C11"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo c11" }
+ [PSCustomObject]@{ Algorithm = "Dedal"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo dedal" } # CryptoDredge-v0.26.0 is fastest
+ [PSCustomObject]@{ Algorithm = "Exosis"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo exosis" }
+ [PSCustomObject]@{ Algorithm = "Geek"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo geek" }
+ [PSCustomObject]@{ Algorithm = "Ghostrider"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo ghostrider" }
+ [PSCustomObject]@{ Algorithm = "GlobalHash"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo glt-globalhash" }
+ [PSCustomObject]@{ Algorithm = "HeavyHash"; Type = "NVIDIA"; Fee = @(0.02); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo heavyhash" }
+ [PSCustomObject]@{ Algorithm = "Hex"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo hex" }
+ [PSCustomObject]@{ Algorithm = "Hmq1725"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 30); Arguments = " --algo hmq1725" } # CryptoDredge-v0.26.0 is fastest
+ # [PSCustomObject]@{ Algorithm = "Honeycomb"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo honeycomb" } # Algo broken, last working version is 0.17.6
+ [PSCustomObject]@{ Algorithm = "JeongHash"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo glt-jeonghash" } # Trex-v0.25.12 is fastest
+ [PSCustomObject]@{ Algorithm = "KawPoW"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = ($Pools."KawPoW".DAGSize + 0.95GB) / 1GB;; MinerSet = 1; WarmupTimes = @(45, 0); Arguments = " --algo kawpow" } # NBMiner-v40.1 is fastest
+ [PSCustomObject]@{ Algorithm = "Lyra2RE3"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo lyra2v3" } # CcminerLyraYesscrypt-v8.21r18v5 is fastest
+ [PSCustomObject]@{ Algorithm = "Lyra2TDC"; Type = "NVIDIA"; Fee = @(0.02); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo lyra2tdc" }
+ [PSCustomObject]@{ Algorithm = "MegaBtx"; Type = "NVIDIA"; Fee = @(0.02); MinMemGB = 1; MinerSet = 0; WarmupTimes = @(45, 15); Arguments = " --algo megabtx" }
+ [PSCustomObject]@{ Algorithm = "MegaMec"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 1; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo megamec" }
+ [PSCustomObject]@{ Algorithm = "Minotaur"; Type = "NVIDIA"; Fee = @(0.05); MinMemGB = 1; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo minotaur" }
+ [PSCustomObject]@{ Algorithm = "MTP"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 3; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo mtp" } # Trex-v0.25.12 is fastest
+ [PSCustomObject]@{ Algorithm = "MTPTrc"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 3; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo mtp-trc" }
+ [PSCustomObject]@{ Algorithm = "PadiHash"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo glt-padihash" }
+ [PSCustomObject]@{ Algorithm = "PawelHash"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo glt-pawelhash" } # Trex-v0.25.12 is fastest
+ [PSCustomObject]@{ Algorithm = "Phi"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo phi" }
+ [PSCustomObject]@{ Algorithm = "Phi5"; Type = "NVIDIA"; Fee = @(0.02); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo phi5" }
+ [PSCustomObject]@{ Algorithm = "Polytimos"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo polytimos" }
+ [PSCustomObject]@{ Algorithm = "Sha256csm"; Type = "NVIDIA"; Fee = @(0.02); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo sha256csm" }
+ # [PSCustomObject]@{ Algorithm = "Sha256t"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo sha256t" } # Takes too long until it starts mining
+ [PSCustomObject]@{ Algorithm = "Sha256q"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo sha256q" }
+ [PSCustomObject]@{ Algorithm = "Renesis"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo renesis" }
+ [PSCustomObject]@{ Algorithm = "Skein2"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo skein2" } # CcminerAlexis78-v1.5.2 is fastest
+ [PSCustomObject]@{ Algorithm = "SkunkHash"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo skunkhash" } # CryptoDredge-v0.26.0 is fastest
+ [PSCustomObject]@{ Algorithm = "Sonoa"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo sonoa" } # Trex-v0.25.12 is fastest
+ [PSCustomObject]@{ Algorithm = "Timetravel"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo timetravel" }
+ [PSCustomObject]@{ Algorithm = "Tribus"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo tribus" }
+ [PSCustomObject]@{ Algorithm = "X11k"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo x11k" }
+ [PSCustomObject]@{ Algorithm = "X16r"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(45, 0); Arguments = " --algo x16r" } # Trex-v0.25.12 is fastest
+ [PSCustomObject]@{ Algorithm = "X16rt"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo x16rt" }
+ [PSCustomObject]@{ Algorithm = "X16rv2"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 3; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo x16rv2" }
+ [PSCustomObject]@{ Algorithm = "X16s"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo x16s" } # Trex-v0.25.12 is fastest
+ [PSCustomObject]@{ Algorithm = "X17"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo x17" }
+ [PSCustomObject]@{ Algorithm = "X17r"; Type = "NVIDIA"; Fee = @(0.02); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo x17r --protocol ufo2" }
+ [PSCustomObject]@{ Algorithm = "X21s"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 1; WarmupTimes = @(30, 15); Arguments = " --algo x21s" } # Trex-v0.25.12 is fastest
+ # [PSCustomObject]@{ Algorithm = "X22i"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 3; MinerSet = 1; WarmupTimes = @(60, 15); Arguments = " --algo x22i" } # No results; Trex-v0.25.12 is fastest
+ [PSCustomObject]@{ Algorithm = "X33"; Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo x33" }
+ [PSCustomObject]@{ Algorithm = "WildKeccak"; Type = "NVIDIA"; Fee = @(0.02); MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo wildkeccak" }
+)
+
+If ($Algorithms = $Algorithms | Where-Object MinerSet -LE $Config.MinerSet | Where-Object { $Pools.($_.Algorithm).Host }) {
+
+ $Devices | Select-Object Type, Model -Unique | ForEach-Object {
+
+ $Miner_Devices = $Devices | Where-Object Type -EQ $_.Type | Where-Object Model -EQ $_.Model
+
+ $MinerAPIPort = [UInt16]($Config.APIPort + ($Miner_Devices | Sort-Object Id | Select-Object -First 1 -ExpandProperty Id) * 2 + 1)
+
+ $Algorithms | Where-Object Type -EQ $_.Type | ForEach-Object {
+
+ If ($AvailableMiner_Devices = $Miner_Devices | Where-Object MemoryGB -ge $_.MinMemGB) {
+
+ $Miner_Name = (@($Name) + @($AvailableMiner_Devices.Model | Sort-Object -Unique | ForEach-Object { $Model = $_; "$(@($AvailableMiner_Devices | Where-Object Model -EQ $Model).Count)x$Model" }) | Select-Object) -join '-' -replace ' ' -replace ' '
+
+ # Get arguments for available miner devices
+ # $_.Arguments = Get-ArgumentsPerDevice -Arguments $_.Arguments -ExcludeArguments @("algo") -DeviceIDs $AvailableMiner_Devices.$DeviceEnumerator
+
+ [PSCustomObject]@{
+ Name = $Miner_Name
+ DeviceName = $AvailableMiner_Devices.Name
+ Type = $AvailableMiner_Devices.Type
+ Path = $Path
+ Arguments = ("$($_.Arguments) --api-port $MinerAPIPort --url stratum+tcp$(if ($Pools.$Algorithm_Norm.SSL) { "s" })://$($Pools.($_.Algorithm).Host):$($Pools.($_.Algorithm).Port) --user $($Pools.($_.Algorithm).User) --pass $($Pools.($_.Algorithm).Pass) --multiple-instance --opencl-threads auto --opencl-launch auto --opencl-platforms $($AvailableMiner_Devices.PlatformId | Sort-Object -Unique) --opencl-devices $(($AvailableMiner_Devices.$DeviceEnumerator | Sort-Object -Unique | ForEach-Object { '{0:x}' -f $_ }) -join ',')" -replace "\s+", " ").trim()
+ Algorithm = $_.Algorithm
+ API = "XmRig"
+ Port = $MinerAPIPort
+ URI = $Uri
+ Fee = $_.Fee # subtract devfee
+ MinerUri = "http://localhost:$($MinerAPIPort)"
+ WarmupTimes = $_.WarmupTimes # First value: seconds until miner must send first sample, if no sample is received miner will be marked as failed; Second value: seconds until miner sends stable hashrates that will count for benchmarking
+ EnvVars = @("GPU_MAX_WORKGROUP_SIZE=256")
+ }
+ }
+ }
+ }
+}
diff --git a/Miners/XmRig-v6.17.0.ps1 b/Miners/XmRig-v6.17.0.ps1
new file mode 100644
index 0000000000..b89d1c777b
--- /dev/null
+++ b/Miners/XmRig-v6.17.0.ps1
@@ -0,0 +1,166 @@
+using module ..\Includes\Include.psm1
+
+$Devices = $Variables.EnabledDevices
+
+$Uri = Switch ($Variables.DriverVersion.CUDA) {
+ { $_ -ge "11.6" } { "https://github.com/RainbowMiner/miner-binaries/releases/download/v6.17.0-xmrig/xmrig-6.17.0-msvc-cuda11_6-win64.7z"; Break }
+ { $_ -ge "11.5" } { "https://github.com/RainbowMiner/miner-binaries/releases/download/v6.17.0-xmrig/xmrig-6.17.0-msvc-cuda11_5-win64.7z"; Break }
+ { $_ -ge "11.4" } { "https://github.com/RainbowMiner/miner-binaries/releases/download/v6.17.0-xmrig/xmrig-6.17.0-msvc-cuda11_4-win64.7z"; Break }
+ { $_ -ge "11.3" } { "https://github.com/RainbowMiner/miner-binaries/releases/download/v6.17.0-xmrig/xmrig-6.17.0-msvc-cuda11_3-win64.7z"; Break }
+ { $_ -ge "11.2" } { "https://github.com/RainbowMiner/miner-binaries/releases/download/v6.17.0-xmrig/xmrig-6.17.0-msvc-cuda11_2-win64.7z"; Break }
+ { $_ -ge "11.1" } { "https://github.com/RainbowMiner/miner-binaries/releases/download/v6.17.0-xmrig/xmrig-6.17.0-msvc-cuda11_1-win64.7z"; Break }
+ { $_ -ge "11.0" } { "https://github.com/RainbowMiner/miner-binaries/releases/download/v6.17.0-xmrig/xmrig-6.17.0-msvc-cuda11_0-win64.7z"; Break }
+ { $_ -ge "10.2" } { "https://github.com/RainbowMiner/miner-binaries/releases/download/v6.17.0-xmrig/xmrig-6.17.0-msvc-cuda10_2-win64.7z"; Break }
+ { $_ -ge "10.1" } { "https://github.com/RainbowMiner/miner-binaries/releases/download/v6.17.0-xmrig/xmrig-6.17.0-msvc-cuda10_1-win64.7z"; Break }
+ { $_ -ge "10.0" } { "https://github.com/RainbowMiner/miner-binaries/releases/download/v6.17.0-xmrig/xmrig-6.17.0-msvc-cuda10_0-win64.7z"; Break }
+ { $_ -ge "9.2" } { "https://github.com/RainbowMiner/miner-binaries/releases/download/v6.17.0-xmrig/xmrig-6.17.0-msvc-cuda9_2-win64.7z"; Break }
+ { $_ -ge "9.1" } { "https://github.com/RainbowMiner/miner-binaries/releases/download/v6.17.0-xmrig/xmrig-6.17.0-msvc-cuda9_1-win64.7z"; Break }
+ { $_ -ge "9.0" } { "https://github.com/RainbowMiner/miner-binaries/releases/download/v6.17.0-xmrig/xmrig-6.17.0-msvc-cuda9_0-win64.7z"; Break }
+ { $_ -ge "8.0" } { "https://github.com/RainbowMiner/miner-binaries/releases/download/v6.17.0-xmrig/xmrig-6.17.0-msvc-cuda8_0-win64.7z"; Break }
+ Default { Return }
+}
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$Path = ".\Bin\$($Name)\xmrig.exe"
+$DeviceEnumerator = "PlatformId_Index"
+
+$Algorithms = [PSCustomObject[]]@(
+ [PSCustomObject]@{ Algorithm = "AstroBWT"; Type = "AMD"; MinMemGB = 0.02; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo astrobwt" }
+ [PSCustomObject]@{ Algorithm = "AstroBWTV2"; Type = "AMD"; MinMemGB = 0.02; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo astrobwt/v2" }
+ [PSCustomObject]@{ Algorithm = "Cryptonight"; Type = "AMD"; MinMemGB = 2; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn/0" }
+ [PSCustomObject]@{ Algorithm = "CryptonightCcx"; Type = "AMD"; MinMemGB = 2; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn/ccx" } # SRBMinerMulti-v0.9.4 is fastest, but has 0.85% miner fee
+ [PSCustomObject]@{ Algorithm = "CryptonightDouble"; Type = "AMD"; MinMemGB = 2; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn/double" }
+ [PSCustomObject]@{ Algorithm = "CryptonightFast"; Type = "AMD"; MinMemGB = 2; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn/fast" }
+ [PSCustomObject]@{ Algorithm = "CryptonightLite"; Type = "AMD"; MinMemGB = 1; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn-lite/0" }
+ [PSCustomObject]@{ Algorithm = "CryptonightLiteV1"; Type = "AMD"; MinMemGB = 1; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn-lite/1" }
+ [PSCustomObject]@{ Algorithm = "CryptonightHalf"; Type = "AMD"; MinMemGB = 2; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn/half" }
+ [PSCustomObject]@{ Algorithm = "CryptonightHeavy"; Type = "AMD"; MinMemGB = 4; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn-heavy/0" }
+ [PSCustomObject]@{ Algorithm = "CryptonightHeavyTube"; Type = "AMD"; MinMemGB = 4; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn-heavy/tube" }
+ [PSCustomObject]@{ Algorithm = "CryptonightPico"; Type = "AMD"; MinMemGB = 0.25; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-pico" }
+ [PSCustomObject]@{ Algorithm = "CryptonightPicoTlo"; Type = "AMD"; MinMemGB = 0.25; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-pico/tlo" }
+ # [PSCustomObject]@{ Algorithm = "CryptonightR"; Type = "AMD"; MinMemGB = 2; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn/r" } # Is never profitable
+ [PSCustomObject]@{ Algorithm = "CryptonightRto"; Type = "AMD"; MinMemGB = 2; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn/rto" }
+ [PSCustomObject]@{ Algorithm = "CryptonightRwz"; Type = "AMD"; MinMemGB = 2; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn/rwz" }
+ [PSCustomObject]@{ Algorithm = "CryptonightV1"; Type = "AMD"; MinMemGB = 2; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn/1" }
+ [PSCustomObject]@{ Algorithm = "CryptonightV2"; Type = "AMD"; MinMemGB = 2; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn/2" }
+ [PSCustomObject]@{ Algorithm = "CryptonightXao"; Type = "AMD"; MinMemGB = 2; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn/xao" }
+ [PSCustomObject]@{ Algorithm = "CryptonightXhvTube"; Type = "AMD"; MinMemGB = 4; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn-heavy/xhv" }
+ [PSCustomObject]@{ Algorithm = "CryptonightZls"; Type = "AMD"; MinMemGB = 2; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo cn/zls" }
+ [PSCustomObject]@{ Algorithm = "KawPoW"; Type = "AMD"; MinMemGB = ($Pools."KawPoW".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(60, 15); Arguments = " --algo kawpow" } # NBMiner-v40.1 is fastest, but has 2% miner fee
+ # [PSCustomObject]@{ Algorithm = "RandomX"; Type = "AMD"; MinMemGB = 3; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo rx/0" } # Not profitable at all
+ [PSCustomObject]@{ Algorithm = "RandomxArq"; Type = "AMD"; MinMemGB = 4; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo rx/arq" }
+ [PSCustomObject]@{ Algorithm = "RandomxKeva"; Type = "AMD"; MinMemGB = 1; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo rx/keva" }
+ [PSCustomObject]@{ Algorithm = "RandomxLoki"; Type = "AMD"; MinMemGB = 2; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo rx/loki" }
+ [PSCustomObject]@{ Algorithm = "RandomxSfx"; Type = "AMD"; MinMemGB = 2; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo rx/sfx" }
+ [PSCustomObject]@{ Algorithm = "RandomxWow"; Type = "AMD"; MinMemGB = 3; MinerSet = 2; WarmupTimes = @(45, 0); Arguments = " --algo rx/wow" }
+ [PSCustomObject]@{ Algorithm = "Uplexa"; Type = "AMD"; MinMemGB = 0.25; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo rx/upx2" }
+
+ [PSCustomObject]@{ Algorithm = "Argon2Chukwa"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo argon2/chukwa" }
+ [PSCustomObject]@{ Algorithm = "Argon2ChukwaV2"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo argon2/chukwav2" }
+ [PSCustomObject]@{ Algorithm = "Argon2Ninja"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo argon2/ninja" }
+ [PSCustomObject]@{ Algorithm = "Argon2WRKZ"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo argon2/wrkz" }
+ [PSCustomObject]@{ Algorithm = "AstroBWT"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo astrobwt" }
+ [PSCustomObject]@{ Algorithm = "AstroBWTV2"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo astrobwt/v2" }
+ [PSCustomObject]@{ Algorithm = "Cryptonight"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/0" }
+ [PSCustomObject]@{ Algorithm = "CryptonightCcx"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/ccx" }
+ [PSCustomObject]@{ Algorithm = "CryptonightDouble"; Type = "CPU"; MinerSet = 1; WarmupTimes = @(45, 0); Arguments = " --algo cn/double" } # XmrStak-v2.10.8 is fastest
+ [PSCustomObject]@{ Algorithm = "CryptonightFast"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/fast" }
+ [PSCustomObject]@{ Algorithm = "CryptonightLite"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-lite/0" }
+ [PSCustomObject]@{ Algorithm = "CryptonightLiteV1"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-lite/1" }
+ [PSCustomObject]@{ Algorithm = "CryptonightHalf"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/half" }
+ [PSCustomObject]@{ Algorithm = "CryptonightHeavy"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-heavy/0" }
+ [PSCustomObject]@{ Algorithm = "CryptonightHeavyTube"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-heavy/tube" }
+ [PSCustomObject]@{ Algorithm = "CryptonightPico"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-pico" }
+ [PSCustomObject]@{ Algorithm = "CryptonightPicoTlo"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-pico/tlo" }
+ # [PSCustomObject]@{ Algorithm = "CryptonightR"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/r" } # Is never profitable
+ [PSCustomObject]@{ Algorithm = "CryptonightRto"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/rto" }
+ [PSCustomObject]@{ Algorithm = "CryptonightRwz"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/rwz" }
+ [PSCustomObject]@{ Algorithm = "CryptonightUpx"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/upx2" }
+ [PSCustomObject]@{ Algorithm = "CryptonightV1"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/1" }
+ [PSCustomObject]@{ Algorithm = "CryptonightV2"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/2" }
+ [PSCustomObject]@{ Algorithm = "CryptonightXao"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/xao" }
+ [PSCustomObject]@{ Algorithm = "CryptonightXhvTube"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-heavy/xhv" }
+ [PSCustomObject]@{ Algorithm = "CryptonightZls"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/zls" }
+ # [PSCustomObject]@{ Algorithm = "RandomX"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo rx/0" } # Not profitable at all
+ [PSCustomObject]@{ Algorithm = "RandomxArq"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo rx/arq" } # SRBMinerMulti-v0.9.4 is fastest, but has 0.85% miner fee
+ [PSCustomObject]@{ Algorithm = "RandomxKeva"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo rx/keva" }
+ [PSCustomObject]@{ Algorithm = "RandomxLoki"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo rx/loki" }
+ [PSCustomObject]@{ Algorithm = "RandomxSfx"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo rx/sfx" } # SRBMinerMulti-v0.9.4 is fastest, but has 0.85% miner fee
+ [PSCustomObject]@{ Algorithm = "RandomxWow"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo rx/wow" }
+ [PSCustomObject]@{ Algorithm = "Uplexa"; Type = "CPU"; MinMemGB = 0; WarmupTimes = @(45, 0); Arguments = " --algo rx/upx2" }
+
+ [PSCustomObject]@{ Algorithm = "AstroBWT"; Type = "NVIDIA"; MinMemGB = 0.02; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo astrobwt" }
+ [PSCustomObject]@{ Algorithm = "AstroBWTV2"; Type = "NVIDIA"; MinMemGB = 0.02; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo astrobwt/v2" }
+ [PSCustomObject]@{ Algorithm = "Cryptonight"; Type = "NVIDIA"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/0" }
+ [PSCustomObject]@{ Algorithm = "CryptonightCcx"; Type = "NVIDIA"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/ccx" } # CryptoDredge-v0.26.0 is fastest, but has 1% miner fee
+ [PSCustomObject]@{ Algorithm = "CryptonightDouble"; Type = "NVIDIA"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/double" }
+ [PSCustomObject]@{ Algorithm = "CryptonightFast"; Type = "NVIDIA"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/fast" }
+ [PSCustomObject]@{ Algorithm = "CryptonightLite"; Type = "NVIDIA"; MinMemGB = 1; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-lite/0" }
+ [PSCustomObject]@{ Algorithm = "CryptonightLiteV1"; Type = "NVIDIA"; MinMemGB = 1; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-lite/1" }
+ [PSCustomObject]@{ Algorithm = "CryptonightHalf"; Type = "NVIDIA"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/half" } # CryptoDredge-v0.26.0 is fastest, but has 1% miner fee
+ [PSCustomObject]@{ Algorithm = "CryptonightHeavy"; Type = "NVIDIA"; MinMemGB = 4; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-heavy/0" }
+ [PSCustomObject]@{ Algorithm = "CryptonightHeavyTube"; Type = "NVIDIA"; MinMemGB = 1; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-heavy/tube" }
+ [PSCustomObject]@{ Algorithm = "CryptonightPico"; Type = "NVIDIA"; MinMemGB = 0.25; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-pico" }
+ [PSCustomObject]@{ Algorithm = "CryptonightPicoTlo"; Type = "NVIDIA"; MinMemGB = 0.25; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-pico/tlo" }
+ # [PSCustomObject]@{ Algorithm = "CryptonightR"; Type = "NVIDIA"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/r" } # Is never profitable
+ [PSCustomObject]@{ Algorithm = "CryptonightRto"; Type = "NVIDIA"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/rto" }
+ [PSCustomObject]@{ Algorithm = "CryptonightRwz"; Type = "NVIDIA"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/rwz" }
+ [PSCustomObject]@{ Algorithm = "CryptonightV1"; Type = "NVIDIA"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/1" }
+ [PSCustomObject]@{ Algorithm = "CryptonightV2"; Type = "NVIDIA"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/2" }
+ [PSCustomObject]@{ Algorithm = "CryptonightXao"; Type = "NVIDIA"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/xao" }
+ [PSCustomObject]@{ Algorithm = "CryptonightXhvTube"; Type = "NVIDIA"; MinMemGB = 4; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn-heavy/xhv" }
+ [PSCustomObject]@{ Algorithm = "CryptonightZls"; Type = "NVIDIA"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo cn/zls" }
+ [PSCustomObject]@{ Algorithm = "KawPoW"; Type = "NVIDIA"; MinMemGB = ($Pools."KawPoW".DAGSize + 0.95GB) / 1GB; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo kawpow" } # Trex-v0.25.12 is fastest, but has 1% miner fee
+ # [PSCustomObject]@{ Algorithm = "RandomX"; Type = "NVIDIA"; MinMemGB = 3; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo rx/0" } # Not profitable at all
+ [PSCustomObject]@{ Algorithm = "RandomxArq"; Type = "NVIDIA"; MinMemGB = 4; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo rx/arq" }
+ [PSCustomObject]@{ Algorithm = "RandomxKeva"; Type = "NVIDIA"; MinMemGB = 1; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo rx/keva" }
+ [PSCustomObject]@{ Algorithm = "RandomxLoki"; Type = "NVIDIA"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo rx/loki" }
+ [PSCustomObject]@{ Algorithm = "RandomxSfx"; Type = "NVIDIA"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo rx/sfx" }
+ [PSCustomObject]@{ Algorithm = "RandomxWow"; Type = "NVIDIA"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo rx/wow" }
+ [PSCustomObject]@{ Algorithm = "Uplexa"; Type = "NVIDIA"; MinMemGB = 0.5; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo rx/upx2" }
+)
+
+If ($Algorithms = $Algorithms | Where-Object MinerSet -LE $Config.MinerSet | Where-Object { $Pools.($_.Algorithm).Host }) {
+
+ $Devices | Select-Object Type, Model -Unique | ForEach-Object {
+
+ $Miner_Devices = $Devices | Where-Object Type -EQ $_.Type | Where-Object Model -EQ $_.Model
+
+ $MinerAPIPort = [UInt16]($Config.APIPort + ($Miner_Devices | Sort-Object Id | Select-Object -First 1 -ExpandProperty Id) * 2 + 1)
+
+ $Algorithms | Where-Object Type -EQ $_.Type | ConvertTo-Json | ConvertFrom-Json | ForEach-Object {
+
+ $MinMemGB = $_.MinMemGB
+
+ If ($AvailableMiner_Devices = $Miner_Devices | Where-Object { $_.Type -eq "CPU" -or $_.MemoryGB -gt $MinMemGB }) {
+
+ $Miner_Name = (@($Name) + @($AvailableMiner_Devices.Model | Sort-Object -Unique | ForEach-Object { $Model = $_; "$(@($AvailableMiner_Devices | Where-Object Model -EQ $Model).Count)x$Model" }) | Select-Object) -join '-' -replace ' ' -replace ' '
+
+ $Arguments = $_.Arguments
+
+ If ($_.Type -eq "CPU") { $Arguments += " --threads=$($AvailableMiner_Devices.CIM.NumberOfLogicalProcessors -1)" }
+ Else { $Arguments += " --no-cpu --opencl --opencl-platform $($AvailableMiner_Devices.PlatformId) --opencl-devices=$(($AvailableMiner_Devices.$DeviceEnumerator | Sort-Object -Unique | ForEach-Object { '{0:x}' -f $_ }) -join ',')" }
+
+ # Optionally disable dev fee mining, requires change in source code
+ # If ($Config.DisableMinerFee) {
+ # $_.Arguments += " --donate-level 0"
+ # $_.Fee = 0
+ # }
+
+ [PSCustomObject]@{
+ Name = $Miner_Name
+ DeviceName = $AvailableMiner_Devices.Name
+ Type = $AvailableMiner_Devices.Type
+ Path = $Path
+ Arguments = ("$($Arguments) $(If ($Pools.($_.Algorithm).BaseName -eq "NiceHash") { " --nicehash" } )$(If ($Pools.($_.Algorithm).SSL) { " --tls" } ) --url=$($Pools.($_.Algorithm).Host):$($Pools.($_.Algorithm).Port) --user=$($Pools.($_.Algorithm).User) --pass=$($Pools.($_.Algorithm).Pass) --rig-id $($Pools.($_.Algorithm).User -split "\." | Select-Object -Index 1) --keepalive --http-enabled --http-host=127.0.0.1 --http-port=$($MinerAPIPort) --api-worker-id=$($Config.WorkerName) --api-id=$($Miner_Name) --retries=90 --retry-pause=1" -replace "\s+", " ").trim()
+ Algorithm = $_.Algorithm
+ API = "XmRig"
+ Port = $MinerAPIPort
+ URI = $Uri
+ Fee = 0.01
+ WarmupTimes = $_.WarmupTimes # First value: seconds until miner must send first sample, if no sample is received miner will be marked as failed; Second value: seconds until miner sends stable hashrates that will count for benchmarking
+ MinerUri = "http://workers.xmrig.info/worker?url=$([System.Web.HTTPUtility]::UrlEncode("http://localhost:$($MinerAPIPort)"))?Authorization=Bearer $([System.Web.HTTPUtility]::UrlEncode($Miner_Name))"
+ }
+ }
+ }
+ }
+}
diff --git a/Miners/XmrStak-v2.10.8.ps1 b/Miners/XmrStak-v2.10.8.ps1
new file mode 100644
index 0000000000..4caeb287bb
--- /dev/null
+++ b/Miners/XmrStak-v2.10.8.ps1
@@ -0,0 +1,166 @@
+using module ..\Includes\Include.psm1
+
+If (-not ($Devices = $Variables.EnabledDevices | Where-Object { $_.Type -ne "NVIDIA" -or $_.OpenCL.ComputeCapability -lt 8.6})) { Return }
+
+$Uri = "https://github.com/fireice-uk/xmr-stak/releases/download/2.10.8/xmr-stak-win64-2.10.8.7z"
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$Path = ".\Bin\$($Name)\xmr-stak.exe"
+$DeviceEnumerator = "Type_Vendor_Index"
+
+$Algorithms = [PSCustomObject[]]@(
+ [PSCustomObject]@{ Algorithm = "CryptonightBittube2"; MinMemGB = 4; Type = "AMD"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noCPU --noNVIDIA --amd" }
+ [PSCustomObject]@{ Algorithm = "CryptonightGpu"; MinMemGB = 3; Type = "AMD"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noCPU --noNVIDIA --amd" } # SRBMinerMulti-v0.9.4 is fastest, but has 0.85% miner fee
+ [PSCustomObject]@{ Algorithm = "CryptonightLite"; MinMemGB = 1; Type = "AMD"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noCPU --noNVIDIA --amd" }
+ [PSCustomObject]@{ Algorithm = "CryptonightLiteV1"; MinMemGB = 1; Type = "AMD"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noCPU --noNVIDIA --amd" }
+ [PSCustomObject]@{ Algorithm = "CryptonightLiteItbc"; MinMemGB = 1; Type = "AMD"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noCPU --noNVIDIA --amd" }
+ [PSCustomObject]@{ Algorithm = "CryptonightHeavy"; MinMemGB = 1; Type = "AMD"; MinerSet = 1; WarmupTimes = @(75, 15); Arguments = " --noCPU --noNVIDIA --amd" } # XmRig-v6.17.0 is fastest
+ [PSCustomObject]@{ Algorithm = "CryptonightMsr"; MinMemGB = 2; Type = "AMD"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noCPU --noNVIDIA --amd" }
+ [PSCustomObject]@{ Algorithm = "CryptonightR"; MinMemGB = 2; Type = "AMD"; MinerSet = 1; WarmupTimes = @(75, 15); Arguments = " --noCPU --noNVIDIA --amd" } # XmRig-v6.17.0 is fastest
+ [PSCustomObject]@{ Algorithm = "CryptonightDouble"; MinMemGB = 2; Type = "AMD"; MinerSet = 1; WarmupTimes = @(75, 15); Arguments = " --noCPU --noNVIDIA --amd" } # XmRig-v6.17.0 is fastest
+ [PSCustomObject]@{ Algorithm = "CryptonightRwz"; MinMemGB = 2; Type = "AMD"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noCPU --noNVIDIA --amd" }
+ [PSCustomObject]@{ Algorithm = "CryptonightV1"; MinMemGB = 2; Type = "AMD"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noCPU --noNVIDIA --amd" }
+ [PSCustomObject]@{ Algorithm = "CryptonightV2"; MinMemGB = 2; Type = "AMD"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noCPU --noNVIDIA --amd" }
+ # [PSCustomObject]@{ Algorithm = "CryptonightXhv"; MinMemGB = 4; Type = "AMD"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noCPU --noNVIDIA --amd" } # Invalid coin
+ [PSCustomObject]@{ Algorithm = "CryptonightXtl"; MinMemGB = 2; Type = "AMD"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noCPU --noNVIDIA --amd" }
+
+ [PSCustomObject]@{ Algorithm = "CryptonightBittube2"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --noAMD --noNVIDIA --cpu" }
+ [PSCustomObject]@{ Algorithm = "CryptonightGpu"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --noAMD --noNVIDIA --cpu" }
+ [PSCustomObject]@{ Algorithm = "CryptonightLite"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --noAMD --noNVIDIA --cpu" }
+ [PSCustomObject]@{ Algorithm = "CryptonightLiteV1"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --noAMD --noNVIDIA --cpu" }
+ [PSCustomObject]@{ Algorithm = "CryptonightLiteItbc"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --noAMD --noNVIDIA --cpu" }
+ [PSCustomObject]@{ Algorithm = "CryptonightHeavy"; Type = "CPU"; MinerSet = 1; WarmupTimes = @(45, 0); Arguments = " --noAMD --noNVIDIA --cpu" } # XmRig-v6.17.0 is fastest
+ [PSCustomObject]@{ Algorithm = "CryptonightMsr"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --noAMD --noNVIDIA --cpu" }
+ [PSCustomObject]@{ Algorithm = "CryptonightR"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --noAMD --noNVIDIA --cpu" }
+ [PSCustomObject]@{ Algorithm = "CryptonightDouble"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --noAMD --noNVIDIA --cpu" }
+ [PSCustomObject]@{ Algorithm = "CryptonightRwz"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --noAMD --noNVIDIA --cpu" }
+ [PSCustomObject]@{ Algorithm = "CryptonightV1"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --noAMD --noNVIDIA --cpu" }
+ [PSCustomObject]@{ Algorithm = "CryptonightV2"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --noAMD --noNVIDIA --cpu" }
+ [PSCustomObject]@{ Algorithm = "CryptonightXhv"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --noAMD --noNVIDIA --cpu" }
+ [PSCustomObject]@{ Algorithm = "CryptonightXtl"; Type = "CPU"; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --noAMD --noNVIDIA --cpu" }
+
+ [PSCustomObject]@{ Algorithm = "CryptonightBittube2"; MinMemGB = 4; Type = "NVIDIA"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noAMD --noCPU --openCLVendor NVIDIA --nvidia" }
+ [PSCustomObject]@{ Algorithm = "CryptonightGpu"; MinMemGB = 3; Type = "NVIDIA"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noAMD --noCPU --openCLVendor NVIDIA --nvidia" }
+ [PSCustomObject]@{ Algorithm = "CryptonightLite"; MinMemGB = 1; Type = "NVIDIA"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noAMD --noCPU --openCLVendor NVIDIA --nvidia" }
+ [PSCustomObject]@{ Algorithm = "CryptonightLiteV1"; MinMemGB = 1; Type = "NVIDIA"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noAMD --noCPU --openCLVendor NVIDIA --nvidia" }
+ [PSCustomObject]@{ Algorithm = "CryptonightLiteItbc"; MinMemGB = 1; Type = "NVIDIA"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noAMD --noCPU --openCLVendor NVIDIA --nvidia" }
+ [PSCustomObject]@{ Algorithm = "CryptonightHeavy"; MinMemGB = 1; Type = "NVIDIA"; MinerSet = 1; WarmupTimes = @(75, 15); Arguments = " --noAMD --noCPU --openCLVendor NVIDIA --nvidia" } # CryptoDredge-v0.26.0 is fastest
+ [PSCustomObject]@{ Algorithm = "CryptonightMsr"; MinMemGB = 2; Type = "NVIDIA"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noAMD --noCPU --openCLVendor NVIDIA --nvidia" }
+ [PSCustomObject]@{ Algorithm = "CryptonightR"; MinMemGB = 2; Type = "NVIDIA"; MinerSet = 1; WarmupTimes = @(75, 15); Arguments = " --noAMD --noCPU --openCLVendor NVIDIA --nvidia" } # XmRig-v6.17.0 is fastest
+ [PSCustomObject]@{ Algorithm = "CryptonightDouble"; MinMemGB = 2; Type = "NVIDIA"; MinerSet = 1; WarmupTimes = @(75, 15); Arguments = " --noAMD --noCPU --openCLVendor NVIDIA --nvidia" } # XmRig-v6.17.0 is fastest
+ [PSCustomObject]@{ Algorithm = "CryptonightRwz"; MinMemGB = 2; Type = "NVIDIA"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noAMD --noCPU --openCLVendor NVIDIA --nvidia" }
+ [PSCustomObject]@{ Algorithm = "CryptonightV1"; MinMemGB = 2; Type = "NVIDIA"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noAMD --noCPU --openCLVendor NVIDIA --nvidia" }
+ [PSCustomObject]@{ Algorithm = "CryptonightV2"; MinMemGB = 2; Type = "NVIDIA"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noAMD --noCPU --openCLVendor NVIDIA --nvidia" }
+ # [PSCustomObject]@{ Algorithm = "CryptonightXhv"; MinMemGB = 4; Type = "NVIDIA"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noAMD --noCPU --openCLVendor NVIDIA --nvidia" } # Invalid coin
+ [PSCustomObject]@{ Algorithm = "CryptonightXtl"; MinMemGB = 2; Type = "NVIDIA"; MinerSet = 0; WarmupTimes = @(75, 15); Arguments = " --noAMD --noCPU --openCLVendor NVIDIA --nvidia" }
+)
+
+If ($Algorithms = $Algorithms | Where-Object MinerSet -LE $Config.MinerSet | Where-Object { $Pools.($_.Algorithm).Host } | Where-Object { -not $Pools.($_.Algorithm).SSL }) {
+
+ $Currency = @{
+ "CryptonightBittube2" = "cryptonight_bittube2"
+ "CryptonightGpu" = "cryptonight_gpu"
+ "CryptonightLite" = "cryptonight_lite"
+ "CryptonightLiteV1" = "cryptonight_lite_v7"
+ "CryptonightLiteItbc" = "cryptonight_lite_v7_xor"
+ "CryptonightXhv" = "cryptonight_haven"
+ "CryptonightHeavy" = "cryptonight_heavy"
+ "CryptonightMsr" = "cryptonight_masari"
+ "CryptonightR" = "cryptonight_r"
+ "CryptonightDouble" = "cryptonight_v8_double"
+ "CryptonightRwz" = "cryptonight_v8_reversewaltz"
+ "CryptonightV1" = "cryptonight_v7"
+ "CryptonightXtl" = "cryptonight_v7_stellite"
+ "CryptonightV2" = "cryptonight_v8"
+ }
+
+ $Coins = @("aeon7", "bbscoin", "bittube", "freehaven", "graft", "haven", "intense", "masari", "monero" ,"qrl", "ryo", "stellite", "turtlecoin")
+
+ $Devices | Select-Object Type, Model -Unique | ForEach-Object {
+
+ $Miner_Devices = $Devices | Where-Object Type -EQ $_.Type | Where-Object Model -EQ $_.Model
+
+ $MinerAPIPort = [UInt16]($Config.APIPort + ($Miner_Devices | Sort-Object Id | Select-Object -First 1 -ExpandProperty Id) * 2 + 1)
+
+ $Algorithms | Where-Object Type -eq $_.Type | ForEach-Object {
+
+ $MinMemGB = $_.MinMemGB
+
+ If ($AvailableMiner_Devices = $Miner_Devices | Where-Object { $_.Type -eq "CPU" -or $_.MemoryGB -gt $MinMemGB }) {
+
+ $Miner_Name = (@($Name) + @($AvailableMiner_Devices.Model | Sort-Object -Unique | ForEach-Object { $Model = $_; "$(@($AvailableMiner_Devices | Where-Object Model -EQ $Model).Count)x$Model" }) | Select-Object) -join '-' -replace ' '
+
+ # Note: For fine tuning directly edit the config files in the miner binary directory
+ $ConfigFileName = [System.Web.HttpUtility]::UrlEncode("$((@("Config") + @($_.Type) + @(($AvailableMiner_Devices.Model | Sort-Object -Unique | Sort-Object Name | ForEach-Object { $Model = $_; "$(@($AvailableMiner_Devices | Where-Object Model -EQ $Model).Count)x$Model($(($AvailableMiner_Devices | Sort-Object Name | Where-Object Model -eq $Model).Name -join ';'))" } | Select-Object) -join '-') + @($MinerAPIPort) | Select-Object) -join '-').txt")
+ $MinerThreadsConfigFileName = [System.Web.HttpUtility]::UrlEncode("$((@("ThreadsConfig") + @($_.Type) + @($_.Algorithm) + @(($AvailableMiner_Devices.Model | Sort-Object -Unique | Sort-Object Name | ForEach-Object { $Model = $_; "$(@($AvailableMiner_Devices | Where-Object Model -EQ $Model).Count)x$Model($(($AvailableMiner_Devices | Sort-Object Name | Where-Object Model -eq $Model).Name -join ';'))" } | Select-Object) -join '-') | Select-Object) -join '-').txt")
+ $PlatformThreadsConfigFileName = [System.Web.HttpUtility]::UrlEncode("$((@("HwConfig") + @($_.Type) + @($_.Algorithm) + @(($AvailableMiner_Devices.Model | Sort-Object -Unique | Sort-Object Name | ForEach-Object { $Model = $_; "$(@($AvailableMiner_Devices | Where-Object Model -EQ $Model).Count)x$Model($(($AvailableMiner_Devices | Sort-Object Name | Where-Object Model -eq $Model).Name -join ';'))" } | Select-Object) -join '-') | Select-Object) -join '-').txt")
+ $PoolFileName = [System.Web.HttpUtility]::UrlEncode("$((@("PoolConf") + @($(Get-PoolBaseName $Pools.($_.Algorithm).Name)) + @($_.Algorithm) + @($Pools.($_.Algorithm).User) + @($Pools.($_.Algorithm).Pass) | Select-Object) -join '-').txt")
+
+ $Arguments = [PSCustomObject]@{
+ PoolFile = [PSCustomObject]@{
+ FileName = $PoolFileName
+ Content = [PSCustomObject]@{
+ pool_list = @(
+ [PSCustomObject]@{
+ pool_address = "$($Pools.($_.Algorithm).Host):$($Pools.($_.Algorithm).Port)"
+ wallet_address = $Pools.($_.Algorithm).User
+ pool_password = $Pools.($_.Algorithm).Pass
+ use_nicehash = $($Pools.($_.Algorithm).BaseName -eq "NiceHash")
+ use_tls = $Pools.($_.Algorithm).SSL
+ tls_fingerprint = ""
+ pool_weight = 1
+ rig_id = "$($Config.Pools.$($Pools.($_.Algorithm).Name).Worker)"
+ }
+ )
+ currency = $(If ($Coins -icontains $Pools.($_.Algorithm).CoinName) { $Pools.($_.Algorithm).CoinName } Else { $Currency.($_.Algorithm) })
+ }
+ }
+ ConfigFile = [PSCustomObject]@{
+ FileName = $ConfigFileName
+ Content = [PSCustomObject]@{
+ call_timeout = 10
+ retry_time = 10
+ giveup_limit = 0
+ verbose_level = 99
+ print_motd = $true
+ h_print_time = 60
+ aes_override = $null
+ use_slow_memory = "warn"
+ tls_secure_algo = $true
+ daemon_mode = $false
+ flush_stdout = $false
+ output_file = ""
+ httpd_port = [UInt16]$MinerAPIPort
+ http_login = ""
+ http_pass = ""
+ prefer_ipv4 = $true
+ }
+ }
+ Arguments = "--poolconf $PoolFileName --config $ConfigFileName$($_.Arguments) $MinerThreadsConfigFileName --noUAC --httpd $($MinerAPIPort)".trim()
+ Devices = @($AvailableMiner_Devices.$DeviceEnumerator | Sort-Object -Unique)
+ HwDetectArguments = "--poolconf $PoolFileName --config $ConfigFileName$($_.Arguments) $PlatformThreadsConfigFileName --httpd $($MinerAPIPort)".trim()
+ MinerThreadsConfigFileName = $MinerThreadsConfigFileName
+ Platform = $Platform
+ PlatformThreadsConfigFileName = $PlatformThreadsConfigFileName
+ Threads = 1
+ }
+
+ If ($AvailableMiner_Devices.PlatformId) { $Arguments.ConfigFile.Content | Add-Member "platform_index" (($AvailableMiner_Devices | Select-Object PlatformId -Unique).PlatformId) }
+
+ [PSCustomObject]@{
+ Name = $Miner_Name
+ DeviceName = $AvailableMiner_Devices.Name
+ Type = $AvailableMiner_Devices.Type
+ Path = $Path
+ Arguments = $Arguments | ConvertTo-Json -Depth 10 -Compress
+ Algorithm = $_.Algorithm
+ API = "Fireice"
+ Port = $MinerAPIPort
+ URI = $Uri
+ Fee = @(0.02)
+ MinerUri = "http://localhost:$($MinerAPIPort)/h"
+ WarmupTimes = $_.WarmupTimes # First value: seconds until miner must send first sample, if no sample is received miner will be marked as failed; Second value: seconds until miner sends stable hashrates that will count for benchmarking
+ }
+ }
+ }
+ }
+}
diff --git a/Miners/ZealotEnemy-v2.6.3.ps1 b/Miners/ZealotEnemy-v2.6.3.ps1
new file mode 100644
index 0000000000..38eb0b31e4
--- /dev/null
+++ b/Miners/ZealotEnemy-v2.6.3.ps1
@@ -0,0 +1,68 @@
+using module ..\Includes\Include.psm1
+
+If (-not ($Devices = $Variables.EnabledDevices | Where-Object Type -EQ "NVIDIA")) { Return }
+
+$Uri = Switch ($Variables.DriverVersion.CUDA) {
+ { $_ -ge "11.1" } { "https://github.com/Minerx117/miners/releases/download/Z-Enemy/z-enemy-2.6.3-win-cuda11.1.zip"; Break }
+ Default { Return }
+}
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$Path = ".\Bin\$($Name)\z-enemy.exe"
+$DeviceEnumerator = "Type_Vendor_Index"
+
+$Algorithms = [PSCustomObject[]]@(
+ [PSCustomObject]@{ Algorithm = "Aergo"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 0); Arguments = " --algo aergo --intensity 23" }
+ [PSCustomObject]@{ Algorithm = "BCD"; MinMemGB = 3; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo bcd" }
+ [PSCustomObject]@{ Algorithm = "Bitcore"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 0); Arguments = " --algo bitcore --intensity 22" }
+ [PSCustomObject]@{ Algorithm = "C11"; MinMemGB = 3; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo c11 --intensity 24" }
+ [PSCustomObject]@{ Algorithm = "Hex"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(30, 0); Arguments = " --algo hex --intensity 24" }
+ [PSCustomObject]@{ Algorithm = "KawPoW"; MinMemGB = ($Pools."KawPoW".DAGSize + 0.95GB) / 1GB; MinerSet = 1; WarmupTimes = @(45, 0); Arguments = " --algo kawpow --intensity 23" }
+ [PSCustomObject]@{ Algorithm = "Phi"; MinMemGB = 3; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo phi" }
+ [PSCustomObject]@{ Algorithm = "Phi2"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo phi2" }
+ [PSCustomObject]@{ Algorithm = "Polytimos"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo poly" }
+ # [PSCustomObject]@{ Algorithm = "SkunkHash"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo skunk" } # No hashrate in time
+ # [PSCustomObject]@{ Algorithm = "Sonoa"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo sonoa" } # No hashrate in time
+ [PSCustomObject]@{ Algorithm = "Timetravel"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo timetravel" }
+ # [PSCustomObject]@{ Algorithm = "Tribus"; MinMemGB = 3; MinerSet = 0; WarmupTimes = @(60, 15); Arguments = " --algo tribus" } # No hashrate in time
+ [PSCustomObject]@{ Algorithm = "X16r"; MinMemGB = 3; MinerSet = 0; WarmupTimes = @(30, 15); Arguments = " --algo x16r" } # No hashrate in time
+ [PSCustomObject]@{ Algorithm = "X16rv2"; MinMemGB = 3; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo x16rv2" }
+ [PSCustomObject]@{ Algorithm = "X16s"; MinMemGB = 3; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo x16s" }
+ # [PSCustomObject]@{ Algorithm = "X17"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo x17" } # No hashrate in time
+ [PSCustomObject]@{ Algorithm = "Xevan"; MinMemGB = 2; MinerSet = 0; WarmupTimes = @(45, 0); Arguments = " --algo xevan --intensity 22" }
+ )
+
+If ($Algorithms = $Algorithms | Where-Object MinerSet -LE $Config.MinerSet | Where-Object { $Pools.($_.Algorithm).Host }) {
+
+ $Devices | Select-Object Model -Unique | ForEach-Object {
+
+ $Miner_Devices = $Devices | Where-Object Model -EQ $_.Model
+
+ $MinerAPIPort = [UInt16]($Config.APIPort + ($Miner_Devices | Sort-Object Id | Select-Object -First 1 -ExpandProperty Id) * 2 + 1)
+
+ $Algorithms | ForEach-Object {
+
+ If ($AvailableMiner_Devices = $Miner_Devices | Where-Object MemoryGB -ge $_.MinMemGB) {
+
+ $Miner_Name = (@($Name) + @($AvailableMiner_Devices.Model | Sort-Object -Unique | ForEach-Object { $Model = $_; "$(@($AvailableMiner_Devices | Where-Object Model -EQ $Model).Count)x$Model" }) | Select-Object) -join '-' -replace ' '
+
+ # Get arguments for available miner devices
+ # $_.Arguments = Get-ArgumentsPerDevice -Arguments $_.Arguments -ExcludeArguments @("algo") -DeviceIDs $AvailableMiner_Devices.$DeviceEnumerator
+
+ [PSCustomObject]@{
+ Name = $Miner_Name
+ DeviceName = $AvailableMiner_Devices.Name
+ Type = $AvailableMiner_Devices.Type
+ Path = $Path
+ Arguments = ("$($_.Arguments) --url stratum+tcp://$($Pools.($_.Algorithm).Host):$($Pools.($_.Algorithm).Port) --user $($Pools.($_.Algorithm).User) --pass $($Pools.($_.Algorithm).Pass) --api-bind 0 --api-bind-http $MinerAPIPort --statsavg 5 --retry-pause 1 --quiet --devices $(($AvailableMiner_Devices.$DeviceEnumerator | Sort-Object -Unique | ForEach-Object { '{0:x}' -f $_ }) -join ',')" -replace "\s+", " ").trim()
+ Algorithm = $_.Algorithm
+ API = "Trex"
+ Port = $MinerAPIPort
+ URI = $Uri
+ Fee = 0.01 # dev fee
+ MinerUri = "http://localhost:$($MinerAPIPort)"
+ WarmupTimes = @($_.WarmupTimes) # First value: seconds until miner must send first sample, if no sample is received miner will be marked as failed; Second value: seconds until miner sends stable hashrates that will count for benchmarking
+ }
+ }
+ }
+ }
+}
diff --git a/Miners/bminer.ps1 b/Miners/bminer.ps1
deleted file mode 100644
index 946c65fce5..0000000000
--- a/Miners/bminer.ps1
+++ /dev/null
@@ -1,35 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-Bminer1553\bminer.exe"
-$Uri = "https://www.bminercontent.com/releases/bminer-lite-v15.5.3-747d98e-amd64.zip"
-$Commands = [PSCustomObject]@{
- #"equihashBTG" = " -uri zhash://" #EquihashBTG
- #"equihash144" = " -pers auto -uri equihash1445://" #Equihash144
- #"zhash" = " -pers auto -uri equihash1445://" #Zhash
- #"ethash" = " -uri ethstratum://" #Ethash
- #"cuckoocycle" = " -uri aeternity://" #aeternity
- "beam" = " -uri beam://" #beam
- "grincuckaroo29" = " -uri cuckaroo29://" #grincuckaroo29
- #"grincuckatoo31" = " -uri cuckatoo31://" #grincuckatoo31 (8gb cards work win7,8, 8.1 & Linux. Win10 requires 10gb+vram)
-
-}
-$Port = $Variables.NVIDIAMinerAPITCPPort
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- $Pass = If ($Pools.($Algo).Pass -like "*,*") {$Pools.($Algo).Pass.ToString().replace(',','%2C')} else {$Pools.($Algo).Pass}
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "$($Commands.$_)$($Pools.($Algo).User):$($Pass)@$($Pools.($Algo).Host):$($Pools.($Algo).Port) --fast -max-temperature 94 -nofee -devices $($Config.SelGPUCC) -api 127.0.0.1:$Port"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "bminer"
- Port = $Port
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ccmineralexis78.ps1 b/Miners/ccmineralexis78.ps1
deleted file mode 100644
index 259f5d85f2..0000000000
--- a/Miners/ccmineralexis78.ps1
+++ /dev/null
@@ -1,60 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-Alexis7815\ccminer.exe"
-$Uri = "https://github.com/nemosminer/ccminerAlexis78/releases/download/Alexis78-v1.5/ccminerAlexis78v1.5.7z"
-
-$Commands = [PSCustomObject]@{
- #"keccak" = " -N 2 -m 2 -i 29 -d $($Config.SelGPUCC)" #Keccak
- #"keccakc" = " -N 2 -i 29 -d $($Config.SelGPUCC)" #Keccakc
- #"lyra2v2" = " -d $($Config.SelGPUCC) -N 1" #Lyra2RE2
- #"poly" = " -N 1 -d $($Config.SelGPUCC)" #polytimos
- #"skein" = " -i 28 -N 2 -d $($Config.SelGPUCC)" #Skein
- "skein2" = " -i 29 -d $($Config.SelGPUCC)" #Skein2 1080ti 2080/ti can handle -i 31 for little xtra hashrate
- "x11evo" = " -i 20.75 -d $($Config.SelGPUCC) " #X11evo
- #"bitcore" = "" #Bitcore
- #"blake2s" = " -r 0 -d $($Config.SelGPUCC)" #Blake2s
- #"c11" = " -N 1 -i 21 -d $($Config.SelGPUCC)" #C11
- #"cryptonight" = "" #Cryptonight
- #"decred" = "" #Decred
- #"equihash" = "" #Equihash
- #"ethash" = "" #Ethash
- #"groestl" = "" #Groestl
- #"hmq1725" = "" #hmq1725
- #"hsr" = " -N 1 -d $($Config.SelGPUCC)" #Hsr(testing)
- #"lbry" = " -d $($Config.SelGPUCC)" #Lbry
- #"lyra2z" = "" #Lyra2z
- #"myr-gr" = " -d $($Config.SelGPUCC) -N 1" #MyriadGroestl
- #"neoscrypt" = " -i 15 -d $($Config.SelGPUCC)" #NeoScrypt
- #"nist5" = " -r 0 -d $($Config.SelGPUCC)" #Nist5
- #"pascal" = "" #Pascal
- #"qubit" = "" #Qubit
- #"scrypt" = "" #Scrypt
- #"sia" = "" #Sia
- #"sib" = " -i 21 -d $($Config.SelGPUCC)" #Sib
- #"timetravel" = "" #Timetravel
- #"vanilla" = "" #BlakeVanilla
- #"veltor" = " -i 23 -d $($Config.SelGPUCC)" #Veltor(fastest)
- #"x11gost" = " -i 21 -d $($Config.SelGPUCC) --api-remote" #X11gost
- #"x13" = " -d $($Config.SelGPUCC) -i 20 -N 1" #X13
- #"x17" = " -N 1 -i 20 -d $($Config.SelGPUCC)" #X17
- #"yescrypt" = "" #Yescrypt
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--cuda-schedule 2 -N 1 -R 1 -b $($Variables.NVIDIAMinerAPITCPPort) -a $_ -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort #4068
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ccminerdyn.ps1 b/Miners/ccminerdyn.ps1
deleted file mode 100644
index 91bda066ee..0000000000
--- a/Miners/ccminerdyn.ps1
+++ /dev/null
@@ -1,27 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-ccminerdyn102\ccminer.exe"
-$Uri = "https://github.com/nemosminer/Dynamic-GPU-Miner-Nvidia/releases/download/v1.0.2/ccminerdyn.7z"
-
-$Commands = [PSCustomObject]@{
- "argon2d-dyn" = "" #argon2d-dyn
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--cpu-priority 4 -N 2 -R 1 -b $($Variables.NVIDIAMinerAPITCPPort) -d $($Config.SelGPUCC) -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -a argon2d -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort #4068
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ccminerklaust.ps1 b/Miners/ccminerklaust.ps1
deleted file mode 100644
index c19db2a735..0000000000
--- a/Miners/ccminerklaust.ps1
+++ /dev/null
@@ -1,33 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-CcminerKlausTv3\ccminer.exe"
-$Uri = "https://github.com/nemosminer/ccminer-KlausT-8.21-mod-r18-src-fix/releases/download/v3/ccminerKlausT.7z"
-
-$Commands = [PSCustomObject]@{
- #"neoscrypt" = " -a neoscrypt -d $($Config.SelGPUCC)" #NeoScrypt
- #"yescrypt" = " -a yescrypt -d $($Config.SelGPUCC)" #Yescrypt
- #"yescryptR16" = " -i 13.25 -a yescryptr16 -d $($Config.SelGPUCC)" #YescryptR16
- #"yescryptR16v2" = " -a yescryptr16v2 -d $($Config.SelGPUCC)" #YescryptR16v2
- #"yescryptR24" = " -a yescryptr24 -d $($Config.SelGPUCC)" #YescryptR24
- #"yescryptR8" = " -a yescryptr8 -d $($Config.SelGPUCC)" #YescryptR8
- "lyra2v3" = " -i 24 -a lyra2v3 -d $($Config.SelGPUCC)" #Lyra2v3 NICEHASH
- "lyra2rev3" = " -i 24 -a lyra2v3 -d $($Config.SelGPUCC)" #Lyra2rev3 YIIMP
-}
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--cpu-priority 4 -b $($Variables.NVIDIAMinerAPITCPPort) -N 2 -R 1 -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ccminerlyra2re3.ps1 b/Miners/ccminerlyra2re3.ps1
deleted file mode 100644
index 7bab7f4551..0000000000
--- a/Miners/ccminerlyra2re3.ps1
+++ /dev/null
@@ -1,27 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-CcminerLyra2RE3\ccminer.exe"
-$Uri = "https://github.com/nemosminer/ccminer-KlausT-8.21-mod-r18-src-fix/releases/download/v3/ccminerKlausT.7z"
-
-$Commands = [PSCustomObject]@{
- "lyra2re3" = " -i 24 -a lyra2v3 -d $($Config.SelGPUCC)" #Lyra2RE3 (mining pool hub)
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--cpu-priority 4 -b $($Variables.NVIDIAMinerAPITCPPort) -N 2 -R 1 -o stratum+tcp://$($Pools.($Algo).Host):20534 -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ccminermtp.ps1 b/Miners/ccminermtp.ps1
deleted file mode 100644
index c7c7cc685a..0000000000
--- a/Miners/ccminermtp.ps1
+++ /dev/null
@@ -1,28 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-ccminermtp1117\ccminer.exe"
-$Uri = "https://github.com/nemosminer/ccminerMTP/releases/download/v1.1.17/ccminerMTP1.1.17.7z"
-
-$Commands = [PSCustomObject]@{
- "mtp" = " -i 20.75 -d $($Config.SelGPUCC)" #mtp (requires 6gb+ system ram to run, 4gb is not enough)
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- If ($Algo -eq "mtp" -and $Pools.($Algo).Host -like "*nicehash*") {return}
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--cpu-priority 4 -N 2 -R 1 -b $($Variables.NVIDIAMinerAPITCPPort) -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -a $Algo -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort #4068
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ccminermtpnh.ps1 b/Miners/ccminermtpnh.ps1
deleted file mode 100644
index 0745553089..0000000000
--- a/Miners/ccminermtpnh.ps1
+++ /dev/null
@@ -1,28 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-ccminermtp1115\ccminer.exe"
-$Uri = "https://github.com/nemosminer/ccminer/releases/download/1.1.15/ccminermtp.7z"
-
-$Commands = [PSCustomObject]@{
- "mtp" = " -d $($Config.SelGPUCC)" #mtp (requires 6gb+ system ram to run, 4gb is not enough)
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- If ($Pools.($Algo).Host -notlike "*nicehash*") {return}
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--cpu-priority 4 -i 20.75 -N 2 -R 1 -b $($Variables.NVIDIAMinerAPITCPPort) -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -a $Algo -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort #4068
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ccminerrfv2.ps1 b/Miners/ccminerrfv2.ps1
deleted file mode 100644
index af807b5745..0000000000
--- a/Miners/ccminerrfv2.ps1
+++ /dev/null
@@ -1,28 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-ccminerrfv2101\ccminer.exe"
-$Uri = "https://github.com/nemosminer/CudaMiner/releases/download/1.0.1/ccminerrfv2.7z"
-
-$Commands = [PSCustomObject]@{
- "rfv2" = "" #rfv2
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- If ($Algo -eq "rfv2" -and $Pools.($Algo).Host -like "*zpool*") {return}
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--cpu-priority 4 -N 2 -R 1 -b $($Variables.NVIDIAMinerAPITCPPort) -d $($Config.SelGPUCC) -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -a rfv2 -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort #4068
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ccminersupr16.ps1 b/Miners/ccminersupr16.ps1
deleted file mode 100644
index f2f31e4563..0000000000
--- a/Miners/ccminersupr16.ps1
+++ /dev/null
@@ -1,30 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-ccminersupr161\ccminer.exe"
-$Uri = "https://github.com/nemosminer/ccminer-x16r/releases/download/v1.6.1/ccminer-patch3-161.7z"
-
-$Commands = [PSCustomObject]@{
- "x16r" = " -a x16r -i 23" #x16r
- "x16s" = " -a x16s -i 23" #x16s
- "x17" = " -a x17 -i 23" #x17
- "c11" = " -a c11 -i 23" #c11
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "-N 2 -R 1 -b $($Variables.NVIDIAMinerAPITCPPort) -d $($Config.SelGPUCC) -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort #4068
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ccminersupr20.ps1 b/Miners/ccminersupr20.ps1
deleted file mode 100644
index 848a274475..0000000000
--- a/Miners/ccminersupr20.ps1
+++ /dev/null
@@ -1,29 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-ccminersupr20\ccminer.exe"
-$Uri = "https://github.com/ocminer/suprminer/releases/download/2.0/suprminer-2.0.7z"
-
-$Commands = [PSCustomObject]@{
- "veil" = " -a x16rt -i 21" #veil
- "neoscrypt" = " -a neoscrypt -i 20.85" #neoscrypt
- #"bitcore" = " -a bitcore -i 21" #bitcore
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--cpu-priority 4 -N 2 -R 1 -b $($Variables.NVIDIAMinerAPITCPPort) -d $($Config.SelGPUCC) -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort #4068
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ccminertpruvot.ps1 b/Miners/ccminertpruvot.ps1
deleted file mode 100644
index 5496fa84ab..0000000000
--- a/Miners/ccminertpruvot.ps1
+++ /dev/null
@@ -1,31 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-ccminertpruvot231\ccminer-x64.exe"
-$Uri = "https://github.com/tpruvot/ccminer/releases/download/2.3.1-tpruvot/ccminer-2.3.1-cuda10.7z"
-
-$Commands = [PSCustomObject]@{
- "exosis" = " -a exosis -i 25.75" #exosis
- "allium" = " -a allium -i 22" #allium
- "keccak" = " -a keccak -i 29" #keccak
- "keccakc" = " -a keccakc -i 29" #keccakc
- "phi2" = " -a phi2 -i 22.25" #phi2
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--cpu-priority 4 -N 2 -R 1 -b $($Variables.NVIDIAMinerAPITCPPort) -d $($Config.SelGPUCC) -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort #4068
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ccminerverus.ps1 b/Miners/ccminerverus.ps1
deleted file mode 100644
index 95fc69f0ed..0000000000
--- a/Miners/ccminerverus.ps1
+++ /dev/null
@@ -1,27 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-Ccminerverus34\ccminer.exe"
-$Uri = "https://github.com/nemosminer/ccminerverus/releases/download/v3.4/ccminerverus34.7z"
-
-$Commands = [PSCustomObject]@{
- "verushash" = " -a verus -i 18.84 -d $($Config.SelGPUCC)" #verus
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--cpu-priority 4 -b $($Variables.NVIDIAMinerAPITCPPort) -N 2 -R 1 -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ccminerx21s.ps1 b/Miners/ccminerx21s.ps1
deleted file mode 100644
index f0bd3785b0..0000000000
--- a/Miners/ccminerx21s.ps1
+++ /dev/null
@@ -1,27 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-Ccminerx21s2311\ccminer.exe"
-$Uri = "https://github.com/nemosminer/ccminerx21s/releases/download/v2.3.1.1/ccminerx21s.7z"
-
-$Commands = [PSCustomObject]@{
- "x21s" = " -a x21s -i 20 -d $($Config.SelGPUCC)" #x21s
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--cpu-priority 4 -b $($Variables.NVIDIAMinerAPITCPPort) -N 2 -R 1 -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ccminerx22i.ps1 b/Miners/ccminerx22i.ps1
deleted file mode 100644
index 2f0af029fa..0000000000
--- a/Miners/ccminerx22i.ps1
+++ /dev/null
@@ -1,27 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-Ccminerx22i2311\ccminer.exe"
-$Uri = "https://github.com/nemosminer/ccminer-x22i/releases/download/v2.3.1.1/ccminerx22i2311.7z"
-
-$Commands = [PSCustomObject]@{
- "x22i" = " -a x22i -i 20 -d $($Config.SelGPUCC)" #x22i
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--cpu-priority 4 -b $($Variables.NVIDIAMinerAPITCPPort) -N 2 -R 1 -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ccminerxevan9.ps1 b/Miners/ccminerxevan9.ps1
deleted file mode 100644
index 38c1fc3840..0000000000
--- a/Miners/ccminerxevan9.ps1
+++ /dev/null
@@ -1,28 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-ccminerxevan9\ccminer_x86.exe"
-$Uri = "https://github.com/nemosminer/ccminer-xevan/releases/download/ccminer-xevan/ccminer_x86.7z"
-
-$Commands = [PSCustomObject]@{
- "xevan" = " -i 21 -N 2 -d $($Config.SelGPUCC) " #Xevan
- #"skein" = " -N 1 -d $($Config.SelGPUCC) -i 27" #Skein
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "-b $($Variables.NVIDIAMinerAPITCPPort) -R 1 -a $_ -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ccmineryescrypt.ps1 b/Miners/ccmineryescrypt.ps1
deleted file mode 100644
index 7884af0a9a..0000000000
--- a/Miners/ccmineryescrypt.ps1
+++ /dev/null
@@ -1,36 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-Ccmineryescrypt9\ccminer.exe"
-$Uri = "https://github.com/nemosminer/ccminerKlausTyescrypt/releases/download/v9/ccminerKlausTyescryptv9.7z"
-
-$Commands = [PSCustomObject]@{
- "yescrypt" = " -d $($Config.SelGPUCC)" #Yescrypt
- "yescryptR16" = " -i 13.25 -d $($Config.SelGPUCC)" #YescryptR16
- "yescryptR16v2" = " -d $($Config.SelGPUCC)" #YescryptR16v2
- "yescryptR24" = " -d $($Config.SelGPUCC)" #YescryptR24
- "yescryptR8" = " -d $($Config.SelGPUCC)" #YescryptR8
- "yescryptR32" = " -i 12.49 -d $($Config.SelGPUCC)" #YescryptR32
-}
- switch ($_) {
- "yescryptR32" {$Fee = 0.14} # account for 14% stale shares
- default {$Fee = 0.00}
- }
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--cpu-priority 4 -b $($Variables.NVIDIAMinerAPITCPPort) -N 2 -R 1 -a $_ -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * (1 - $Fee)} # account for 14% stale shares yescryptR32
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/easy-binarium.ps1 b/Miners/easy-binarium.ps1
deleted file mode 100644
index 9427ab122e..0000000000
--- a/Miners/easy-binarium.ps1
+++ /dev/null
@@ -1,71 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\CPU-bubasikBinarium\cpuminer-aes-sse42.exe"
-$Uri = "https://github.com/bubasik/cpuminer-easy-binarium/releases/download/1.0/cpuminer-easy-binarium-win_x64.zip"
-
-$Commands = [PSCustomObject]@{
- # "allium" = "" #Allium
- #"bitcore" = "" #Bitcore
- #"blake2s" = "" #Blake2s
- #"blakecoin" = "" #Blakecoin
- "binarium-v1" = " -a Binarium_hash_v1" #binarium-v1
- #"vanilla" = "" #BlakeVanilla
- #"c11" = "" #C11
- # "cryptonight" = "" #CryptoNight
- #"cryptonightv7" = "" #cryptonightv7
- #"decred" = "" #Decred
- #"equihash" = "" #Equihash
- #"ethash" = "" #Ethash
- #"groestl" = "" #Groestl
- # "hmq1725" = "" #HMQ1725
- # "hodl" = "" #Hodl
- #"jha" = "" #JHA
- #"keccak" = "" #Keccak
- #"lbry" = "" #Lbry
- #"lyra2v2" = "" #Lyra2RE2
- # "lyra2z" = "" #Lyra2z
- # "m7m" = "" #m7m
- #"myr-gr" = "" #MyriadGroestl
- #"neoscrypt" = "" #NeoScrypt
- #"nist5" = "" #Nist5
- #"pascal" = "" #Pascal
- #"sib" = "" #Sib
- #"skein" = "" #Skein
- #"skunk" = "" #Skunk
- #"timetravel" = "" #Timetravel
- #"tribus" = "" #Tribus
- #"veltor" = "" #Veltor
- #"x11evo" = "" #X11evo
- #"x17" = "" #X17
- # "x16r" = "" #X16r
- # "yescrypt" = "" #Yescrypt
- # "yespower" = "" #Yespower
- # "yescryptr16" = "" #YescryptR16
- # "yescryptr32" = "" #YescryptR32
-}
-
-$Name = Get-Item $MyInvocation.MyCommand.Path | Select-Object -ExpandProperty BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
-
- switch ($_) {
- "hodl" {$ThreadCount = $Variables.ProcessorCount}
- "binarium-v1" {$ThreadCount = $Variables.ProcessorCount}
- default {$ThreadCount = $Variables.ProcessorCount - 2}
- }
-
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "CPU"
- Path = $Path
- Arguments = "--cpu-affinity AAAA -q -t $($ThreadCount) -b $($Variables.CPUMinerAPITCPPort) -o $($Pools.($Algo).Protocol)://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Week * 0.68 } # Account for rejected share. Work with pool ops to fix.
- API = "Ccminer"
- Port = $Variables.CPUMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ethminer.ps1 b/Miners/ethminer.ps1
deleted file mode 100644
index 8dcf748586..0000000000
--- a/Miners/ethminer.ps1
+++ /dev/null
@@ -1,27 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-Ethminer0171\ethminer.exe"
-$Uri = "https://github.com/ethereum-mining/ethminer/releases/download/v0.17.1/ethminer-0.17.1-cuda10.0-windows-amd64.zip"
-$Commands = [PSCustomObject]@{
- #"ethash" = "" #Ethash
-}
-$Port = $Variables.NVIDIAMinerAPITCPPort
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- If ($Pools.($Algo).Host -notlike "*nicehash*") {return}
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--cuda-devices $($Config.SelGPUDSTM) --api-port -$Port -U -P stratum://$($Pools.($Algo).User):x@$($Pools.($Algo).Host):$($Pools.($Algo).Port)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ethminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/ewbfv2.ps1 b/Miners/ewbfv2.ps1
deleted file mode 100644
index 3ba493868e..0000000000
--- a/Miners/ewbfv2.ps1
+++ /dev/null
@@ -1,30 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-EWBF06\\miner.exe"
-$Uri = "https://nemosminer.com/data/optional/EWBFEquihashminerv0.6.7z"
-$Commands = [PSCustomObject]@{
- "equihash144" = " --cuda_devices $($Config.SelGPUDSTM) --algo 144_5 --pers auto" #Equihash144
- "zhash" = " --cuda_devices $($Config.SelGPUDSTM) --algo 144_5 --pers auto" #Zhash
- "equihash192" = " --cuda_devices $($Config.SelGPUDSTM) --algo 192_7 --pers ZERO_PoW" #Equihash192
- "equihash-btg" = " --cuda_devices $($Config.SelGPUDSTM) --algo 144_5 --pers BgoldPoW" # Equihash-btg
- "equihash96" = " --cuda_devices $($Config.SelGPUDSTM) --algo 96_5 --pers auto" #Equihash96
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--templimit 95 --api 127.0.0.1:$($Variables.NVIDIAMinerAPITCPPort) --server $($Pools.($Algo).Host) --port $($Pools.($Algo).Port) --eexit 1 --user $($Pools.($Algo).User) --pass $($Pools.($Algo).Pass)$($Commands.$_) --fee 0 --intensity 64"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ewbf"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/jayddeeSse2.ps1 b/Miners/jayddeeSse2.ps1
deleted file mode 100644
index 11179e38e5..0000000000
--- a/Miners/jayddeeSse2.ps1
+++ /dev/null
@@ -1,72 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\CPU-JayDDee\cpuminer-aes-sse42.exe"
-$Uri = "https://github.com/JayDDee/cpuminer-opt/files/1996977/cpuminer-opt-3.8.8.1-windows.zip"
-
-$Commands = [PSCustomObject]@{
- "allium" = "" #Allium
- "argon2d-crds" = ",d=7 " #argon2d-crds
- "argon2d-dyn" = "" #argon2d-dyn
- "argon2d4096" = "" #argon2d4096
- #"bitcore" = "" #Bitcore
- #"blake2s" = "" #Blake2s
- #"blakecoin" = "" #Blakecoin
- #"vanilla" = "" #BlakeVanilla
- #"c11" = "" #C11
- # "cryptonight" = "" #CryptoNight
- #"cryptonightv7" = "" #cryptonightv7
- #"decred" = "" #Decred
- #"equihash" = "" #Equihash
- #"ethash" = "" #Ethash
- #"groestl" = "" #Groestl
- "hmq1725" = "" #HMQ1725
- #"hodl" = "" #Hodl
- #"jha" = "" #JHA
- #"keccak" = "" #Keccak
- #"lbry" = "" #Lbry
- #"lyra2v2" = "" #Lyra2RE2
- "lyra2z" = "" #Lyra2z
- "m7m" = "" #m7m
- #"myr-gr" = "" #MyriadGroestl
- #"neoscrypt" = "" #NeoScrypt
- #"nist5" = "" #Nist5
- #"pascal" = "" #Pascal
- #"sib" = "" #Sib
- #"skein" = "" #Skein
- #"skunk" = "" #Skunk
- #"timetravel" = "" #Timetravel
- #"tribus" = "" #Tribus
- #"veltor" = "" #Veltor
- #"x11evo" = "" #X11evo
- #"x17" = "" #X17
- # "x16r" = "" #X16r
- "yescrypt" = "" #Yescrypt
- "yescryptr8" = "" #YescryptR8
- "yescryptr16" = "" #YescryptR16
- "yescryptr32" = "" #YescryptR32
-}
-
-$Name = Get-Item $MyInvocation.MyCommand.Path | Select-Object -ExpandProperty BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
-
- switch ($_) {
- "hodl" {$ThreadCount = $Variables.ProcessorCount}
- default {$ThreadCount = $Variables.ProcessorCount - 2}
- }
-
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "CPU"
- Path = $Path
- Arguments = "--cpu-affinity AAAA -q -t $($ThreadCount) -b $($Variables.CPUMinerAPITCPPort) -a $_ -o $($Pools.($Algo).Protocol)://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Week}
- API = "Ccminer"
- Port = $Variables.CPUMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/lolMiner-v1.48.ps1 b/Miners/lolMiner-v1.48.ps1
new file mode 100644
index 0000000000..26f9f25dba
--- /dev/null
+++ b/Miners/lolMiner-v1.48.ps1
@@ -0,0 +1,136 @@
+using module ..\Includes\Include.psm1
+
+If (-not ($Devices = $Variables.EnabledDevices | Where-Object Type -in @("AMD", "NVIDIA"))) { Return }
+
+$Uri = "https://github.com/Lolliedieb/lolMiner-releases/releases/download/1.48/lolMiner_v1.48_Win64.zip"
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$Path = ".\Bin\$($Name)\lolminer.exe"
+$DeviceEnumerator = "Bus"
+
+$Algorithms = [PSCustomObject[]]@(
+ [PSCustomObject]@{ Algorithm = @("Blake3"); Type = "AMD"; Fee = @(0.015); MinMemGB = 3.0; MinerSet = 0; WarmupTimes = @(45, 45); Arguments = " --algo ALEPHIUM" }
+ [PSCustomObject]@{ Algorithm = @("Autolykos2"); Type = "AMD"; Fee = @(0.015); MinMemGB = 3.0; MinerSet = 0; WarmupTimes = @(45, 45); Arguments = " --algo AUTOLYKOS2" }
+ [PSCustomObject]@{ Algorithm = @("BeamV3"); Type = "AMD"; Fee = @(0.01); MinMemGB = 6.0; MinerSet = 0; WarmupTimes = @(30, 45); Arguments = " --algo BEAM-III" }
+ [PSCustomObject]@{ Algorithm = @("Cuckoo29"); Type = "AMD"; Fee = @(0.02); MinMemGB = 6.0; MinerSet = 0; WarmupTimes = @(45, 45); Arguments = " --algo C29AE" }
+ [PSCustomObject]@{ Algorithm = @("Cuckaroo29B"); Type = "AMD"; Fee = @(0.02); MinMemGB = 6.0; MinerSet = 0; WarmupTimes = @(30, 45); Arguments = " --algo CR29-40" }
+ [PSCustomObject]@{ Algorithm = @("Cuckaroo29S"); Type = "AMD"; Fee = @(0.02); MinMemGB = 6.0; MinerSet = 0; WarmupTimes = @(30, 45); Arguments = " --algo CR29-32" }
+ [PSCustomObject]@{ Algorithm = @("Cuckaroo30CTX"); Type = "AMD"; Fee = @(0.025); MinMemGB = 7.8; MinerSet = 0; WarmupTimes = @(30, 45); Arguments = " --algo C30CTX" }
+ [PSCustomObject]@{ Algorithm = @("CuckarooD29"); Type = "AMD"; Fee = @(0.01); MinMemGB = 4.0; MinerSet = 1; WarmupTimes = @(30, 45); Arguments = " --algo C29D" } # TeamRedMiner-v0.9.4.2 is fastest, keep enabled because TeamRed does not support algo on Navi
+ [PSCustomObject]@{ Algorithm = @("CuckarooM29"); Type = "AMD"; Fee = @(0.01); MinMemGB = 6.0; MinerSet = 0; WarmupTimes = @(30, 45); Arguments = " --algo C29M" }
+ [PSCustomObject]@{ Algorithm = @("Cuckatoo31"); Type = "AMD"; Fee = @(0.02); MinMemGB = 4.0; MinerSet = 1; WarmupTimes = @(60, 60); Arguments = " --algo C31" } # TeamRedMiner-v0.9.4.2 is fastest
+ [PSCustomObject]@{ Algorithm = @("Cuckatoo32"); Type = "AMD"; Fee = @(0.02); MinMemGB = 4.0; MinerSet = 0; WarmupTimes = @(60, 60); Arguments = " --algo C32" }
+ [PSCustomObject]@{ Algorithm = @("Equihash1445"); Type = "AMD"; Fee = @(0.01); MinMemGB = 3.0; MinerSet = 1; WarmupTimes = @(30, 30); Arguments = " --coin AUTO144_5" } # GMiner-v2.91 is fastest, but des not support Navi
+ [PSCustomObject]@{ Algorithm = @("Equihash1927"); Type = "AMD"; Fee = @(0.01); MinMemGB = 3.0; MinerSet = 1; WarmupTimes = @(30, 45); Arguments = " --coin AUTO192_7" } # GMiner-v2.91 is fastest, but des not support Navi
+ [PSCustomObject]@{ Algorithm = @("Equihash2109"); Type = "AMD"; Fee = @(0.01); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(30, 45); Arguments = " --algo EQUI210_9" }
+ [PSCustomObject]@{ Algorithm = @("Equihash1254"); Type = "AMD"; Fee = @(0.01); MinMemGB = 3.0; MinerSet = 0; WarmupTimes = @(30, 45); Arguments = " --coin ZEL" }
+ [PSCustomObject]@{ Algorithm = @("EtcHash"); Type = "AMD"; Fee = @(0.007); MinMemGB = ($Pools."Etchash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETCHASH" } # Ethereum Classic, PhoenixMiner-v6.1b is faster
+ [PSCustomObject]@{ Algorithm = @("EtcHash", "Blake3"); Type = "AMD"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."Etchash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETCHASH --dualmode ALEPHDUAL" } # Ethereum Classic, PhoenixMiner-v6.1b is faster
+ [PSCustomObject]@{ Algorithm = @("EtcHash", "SHA256ton"); Type = "AMD"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."Etchash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETCHASH --dualmode TONDUAL" } # Ethereum Classic, PhoenixMiner-v6.1b is faster
+ [PSCustomObject]@{ Algorithm = @("Ethash"); Type = "AMD"; Fee = @(0.007); MinMemGB = ($Pools."Ethash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETHASH" } # PhoenixMiner-v6.1b is faster
+ [PSCustomObject]@{ Algorithm = @("Ethash", "Blake3"); Type = "AMD"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."Ethash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETHASH --dualmode ALEPHDUAL" }
+ [PSCustomObject]@{ Algorithm = @("Ethash", "SHA256ton"); Type = "AMD"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."Ethash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETHASH --dualmode TONDUAL" }
+ [PSCustomObject]@{ Algorithm = @("EthashLowMem"); Type = "AMD"; Fee = @(0.007); MinMemGB = ($Pools."EthashLowMem".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETHASH" } # PhoenixMiner-v6.1b is faster
+ [PSCustomObject]@{ Algorithm = @("EthashLowMem", "Blake3"); Type = "AMD"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."EthashLowMem".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETHASH --dualmode ALEPHDUAL" }
+ [PSCustomObject]@{ Algorithm = @("EthashLowMem", "SHA256ton"); Type = "AMD"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."EthashLowMem".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETHASH --dualmode TONDUAL" }
+ [PSCustomObject]@{ Algorithm = @("SHA256ton"); Type = "AMD"; Fee = @(0.01); MinMemGB = 3.0; MinerSet = 2; WarmupTimes = @(15, 30); Arguments = " --algo TON" }
+ [PSCustomObject]@{ Algorithm = @("UbqHash"); Type = "AMD"; Fee = @(0.007); MinMemGB = ($Pools."UbqHash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(30, 60); Arguments = " --algo UBQHASH" }
+ [PSCustomObject]@{ Algorithm = @("UbqHash", "Blake3"); Type = "AMD"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."UbqHash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(30, 60); Arguments = " --algo UBQHASH --dualmode ALEPHDUAL" }
+ [PSCustomObject]@{ Algorithm = @("UbqHash", "SHA256ton"); Type = "AMD"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."UbqHash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(30, 60); Arguments = " --algo UBQHASH --dualmode TONDUAL" }
+
+ [PSCustomObject]@{ Algorithm = @("Blake3"); Type = "NVIDIA"; Fee = @(0.015); MinMemGB = 3.0; MinerSet = 1; WarmupTimes = @(45, 45); Arguments = " --algo ALEPHIUM" }
+ [PSCustomObject]@{ Algorithm = @("Autolykos2"); Type = "NVIDIA"; Fee = @(0.015); MinMemGB = 3.0; MinerSet = 1; WarmupTimes = @(45, 45); Arguments = " --algo AUTOLYKOS2" }
+ [PSCustomObject]@{ Algorithm = @("BeamV3"); Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 6.0; MinerSet = 1; WarmupTimes = @(30, 45); Arguments = " --algo BEAM-III" } # NBMiner-v40.1 is fastest
+ [PSCustomObject]@{ Algorithm = @("Cuckoo29"); Type = "NVIDIA"; Fee = @(0.02); MinMemGB = 6.0; MinerSet = 0; WarmupTimes = @(45, 45); Arguments = " --algo C29AE" }
+ [PSCustomObject]@{ Algorithm = @("Cuckaroo29B"); Type = "NVIDIA"; Fee = @(0.02); MinMemGB = 6.0; MinerSet = 0; WarmupTimes = @(30, 45); Arguments = " --algo CR29-40" }
+ [PSCustomObject]@{ Algorithm = @("Cuckaroo29S"); Type = "NVIDIA"; Fee = @(0.02); MinMemGB = 6.0; MinerSet = 0; WarmupTimes = @(30, 45); Arguments = " --algo CR29-32" }
+ [PSCustomObject]@{ Algorithm = @("Cuckaroo30CTX"); Type = "NVIDIA"; Fee = @(0.025); MinMemGB = 8.0; MinerSet = 0; WarmupTimes = @(30, 45); Arguments = " --algo C30CTX" }
+ [PSCustomObject]@{ Algorithm = @("CuckarooD29"); Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 4.0; MinerSet = 1; WarmupTimes = @(30, 45); Arguments = " --algo C29D" } # GMiner-v2.91 is fastest
+ [PSCustomObject]@{ Algorithm = @("CuckarooM29"); Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 6.0; MinerSet = 0; WarmupTimes = @(30, 45); Arguments = " --algo C29M" }
+ [PSCustomObject]@{ Algorithm = @("Cuckatoo31"); Type = "NVIDIA"; Fee = @(0.02); MinMemGB = 4.0; MinerSet = 0; WarmupTimes = @(60, 60); Arguments = " --algo C31" }
+ [PSCustomObject]@{ Algorithm = @("Cuckatoo32"); Type = "NVIDIA"; Fee = @(0.02); MinMemGB = 4.0; MinerSet = 0; WarmupTimes = @(60, 60); Arguments = " --algo C32" }
+ [PSCustomObject]@{ Algorithm = @("Equihash1445"); Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 3.0; MinerSet = 1; WarmupTimes = @(30, 30); Arguments = " --coin AUTO144_5" } # MiniZ-v1.8 is fastest, but has 2% miner fee
+ [PSCustomObject]@{ Algorithm = @("Equihash1927"); Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 3.0; MinerSet = 1; WarmupTimes = @(30, 45); Arguments = " --coin AUTO192_7" } # MiniZ-v1.8 is fastest, but has 2% miner fee
+ [PSCustomObject]@{ Algorithm = @("Equihash2109"); Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 2.0; MinerSet = 0; WarmupTimes = @(30, 45); Arguments = " --algo EQUI210_9" }
+ [PSCustomObject]@{ Algorithm = @("Equihash1254"); Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 3.0; MinerSet = 1; WarmupTimes = @(30, 45); Arguments = " --coin ZEL" } # MiniZ-v1.8 is fastest, but has 2% miner fee
+ [PSCustomObject]@{ Algorithm = @("EtcHash"); Type = "NVIDIA"; Fee = @(0.007); MinMemGB = ($Pools."Etchash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETCHASH" } # Ethereum Classic, PhoenixMiner-v6.1b is faster
+ [PSCustomObject]@{ Algorithm = @("EtcHash", "Blake3"); Type = "NVIDIA"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."Etchash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETCHASH --dualmode ALEPHDUAL" } # Ethereum Classic, PhoenixMiner-v6.1b is faster
+ [PSCustomObject]@{ Algorithm = @("EtcHash", "SHA256ton"); Type = "NVIDIA"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."Etchash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETCHASH --dualmode TONDUAL" } # Ethereum Classic, PhoenixMiner-v6.1b is faster
+ [PSCustomObject]@{ Algorithm = @("Ethash"); Type = "NVIDIA"; Fee = @(0.007); MinMemGB = ($Pools."Ethash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETHASH" } # PhoenixMiner-v6.1b is faster
+ [PSCustomObject]@{ Algorithm = @("Ethash", "Blake3"); Type = "NVIDIA"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."Ethash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETHASH --dualmode ALEPHDUAL" }
+ [PSCustomObject]@{ Algorithm = @("Ethash", "SHA256ton"); Type = "NVIDIA"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."Ethash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETHASH --dualmode TONDUAL" }
+ [PSCustomObject]@{ Algorithm = @("EthashLowMem"); Type = "NVIDIA"; Fee = @(0.007); MinMemGB = ($Pools."EthashLowMem".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETHASH" } # PhoenixMiner-v6.1b is faster
+ [PSCustomObject]@{ Algorithm = @("EthashLowMem", "Blake3"); Type = "NVIDIA"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."EthashLowMem".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETHASH --dualmode ALEPHDUAL" }
+ [PSCustomObject]@{ Algorithm = @("EthashLowMem", "SHA256ton"); Type = "NVIDIA"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."EthashLowMem".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(45, 45); Arguments = " --algo ETHASH --dualmode TONDUAL" }
+ [PSCustomObject]@{ Algorithm = @("SHA256ton"); Type = "NVIDIA"; Fee = @(0.01); MinMemGB = 3.0; MinerSet = 2; WarmupTimes = @(15, 30); Arguments = " --algo TON" }
+ [PSCustomObject]@{ Algorithm = @("UbqHash"); Type = "NVIDIA"; Fee = @(0.007); MinMemGB = ($Pools."UbqHash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(30, 60); Arguments = " --algo UBQHASH" }
+ [PSCustomObject]@{ Algorithm = @("UbqHash", "Blake3"); Type = "NVIDIA"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."UbqHash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(30, 60); Arguments = " --algo UBQHASH --dualmode ALEPHDUAL" }
+ [PSCustomObject]@{ Algorithm = @("UbqHash", "SHA256ton"); Type = "NVIDIA"; Fee = @(0.01, 0.01); MinMemGB = ($Pools."UbqHash".DAGSize + 0.95GB) / 1GB; MinerSet = 2; WarmupTimes = @(30, 60); Arguments = " --algo UBQHASH --dualmode TONDUAL" }
+)
+
+If ($Algorithms = $Algorithms | Where-Object MinerSet -LE $Config.MinerSet | Where-Object { $Pools.($_.Algorithm[0]).Host -and (-not $_.Algorithm[1] -or $PoolsSecondaryAlgorithm.($_.Algorithm[1]).Host) }) {
+
+ $Devices | Select-Object Type, Model -Unique | ForEach-Object {
+
+ $Miner_Devices = $Devices | Where-Object Type -eq $_.Type | Where-Object Model -EQ $_.Model
+
+ $MinerAPIPort = [UInt16]($Config.APIPort + ($Miner_Devices | Sort-Object Id | Select-Object -First 1 -ExpandProperty Id) * 2 + 1)
+
+ $Algorithms | Where-Object Type -EQ $_.Type | ConvertTo-Json | ConvertFrom-Json | ForEach-Object {
+
+ If ($Pools.($_.Algorithm[0]).DAGSize -gt 0) {
+ If ($Pools.($_.Algorithm[0]).BaseName -in @("MiningPoolHub", "NiceHash", "ProHashing")) { $_.Arguments += " --ethstratum ETHV1" }
+ }
+ If ($_.Algorithm[0] -match "^Cuckaroo.*$|^Cuckoo.*$" -and ([System.Environment]::OSVersion.Version -ge [Version]"10.0.0.0")) { $_.MinMemGB += 1 }
+
+ If ($AvailableMiner_Devices = $Miner_Devices | Where-Object MemoryGB -ge $_.MinMemGB) {
+
+ $Miner_Name = (@($Name) + @($AvailableMiner_Devices.Model | Sort-Object -Unique | ForEach-Object { $Model = $_; "$(@($AvailableMiner_Devices | Where-Object Model -EQ $Model).Count)x$Model" }) + @(If ($_.Algorithm[1]) { "$($_.Algorithm[0])&$($_.Algorithm[1])" }) + @($_.Intensity) | Select-Object) -join '-' -replace ' '
+
+ # Get arguments for available miner devices
+ # $_.Arguments = Get-ArgumentsPerDevice -Arguments $_.Arguments -ExcludeArguments @("algo", "coin") -DeviceIDs $AvailableMiner_Devices.$DeviceEnumerator
+
+ If ($_.Algorithm[0] -eq "SHA256ton") {
+ If ($Pools.($_.Algorithm[0]).BaseName -eq "TonWhales") {
+ $_.Arguments += " --pool wss://stratum.$($Pools.($_.Algorithm[0]).Host)/stratum"
+ }
+ Else {
+ $_.Arguments += " --pool wss://$($Pools.($_.Algorithm[0]).Host)"
+ }
+ }
+ Else {
+ $_.Arguments += "$(If ($Pools.($_.Algorithm[0]).SSL) { " --tls on" } Else { " --tls off" }) --pool $($Pools.($_.Algorithm[0]).Host):$($Pools.($_.Algorithm[0]).Port)"
+ }
+ $_.Arguments += " --user $($Pools.($_.Algorithm[0]).User) --pass $($Pools.($_.Algorithm[0]).pass)$(If ($Pools.($_.Algorithm[0]).BaseName -eq "ProHashing" -and $_.Algorithm[0] -eq "EthashLowMem") { ",l=$((($AvailableMiner_Devices.Memory | Measure-Object -Minimum).Minimum - 0.95GB) / 1GB)" })"
+
+
+ If ($_.Algorithm[1]) {
+ If ($_.Algorithm[1] -eq "SHA256ton") {
+ If ($Pools.($_.Algorithm[1]).BaseName -eq "TonWhales") {
+ $_.Arguments += " --dualpool wss://stratum.$($Pools.($_.Algorithm[1]).Host)/stratum --dualuser $($Pools.($_.Algorithm[1]).User) --dualpass $($Pools.($_.Algorithm[1]).pass)"
+ }
+ Else {
+ $_.Arguments += " --dualpool wss://$($Pools.($_.Algorithm[1]).Host) --dualuser $($Pools.($_.Algorithm[1]).User) --dualpass $($Pools.($_.Algorithm[1]).pass)"
+ }
+ }
+ Else {
+ $_.Arguments += "$(If ($Pools.($_.Algorithm[0]).SSL) { " --dualtls on" } Else { " --dualtls off" }) --dualpool $($Pools.($_.Algorithm[1]).Host):$($Pools.($_.Algorithm[1]).Port) --dualuser $($Pools.($_.Algorithm[1]).User) --dualpass $($Pools.($_.Algorithm[1]).pass)"
+ }
+ }
+
+ [PSCustomObject]@{
+ Name = $Miner_Name
+ DeviceName = $AvailableMiner_Devices.Name
+ Type = $AvailableMiner_Devices.Type
+ Path = $Path
+ Arguments = ("$($_.Arguments) --log off --apiport $MinerAPIPort --shortstats 7 --longstats 30 --watchdog exit --dns-over-https 1 --devicesbypcie --devices $(($AvailableMiner_Devices.$DeviceEnumerator | Sort-Object -Unique | ForEach-Object { '{0}:0' -f $_ }) -join ',')" -replace "\s+", " ").trim()
+ Algorithm = ($_.Algorithm[0], $_.Algorithm[1]) | Select-Object
+ API = "lolMiner"
+ Port = $MinerAPIPort
+ URI = $Uri
+ Fee = $_.Fee
+ WarmupTimes = $_.WarmupTimes # First value: seconds until miner must send first sample, if no sample is received miner will be marked as failed; Second value: seconds until miner sends stable hashrates that will count for benchmarking
+ }
+ }
+ }
+ }
+}
diff --git a/Miners/nheqVerus.ps1 b/Miners/nheqVerus.ps1
deleted file mode 100644
index a47f8366f3..0000000000
--- a/Miners/nheqVerus.ps1
+++ /dev/null
@@ -1,33 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\CPU-nheqVerus\nheqminer.exe"
-$Uri = "https://github.com/VerusCoin/nheqminer/releases/download/0.7.1/nheqminer-Windows-v0.7.1.zip"
-
-$Commands = [PSCustomObject]@{
- "verus" = "" #Verushash
-}
-
-$Name = Get-Item $MyInvocation.MyCommand.Path | Select-Object -ExpandProperty BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
-
- switch ($_) {
- "hodl" {$ThreadCount = $Variables.ProcessorCount}
- default {$ThreadCount = $Variables.ProcessorCount - 2}
- }
-
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "CPU"
- Path = $Path
- Arguments = "-t $($ThreadCount) -a $($Variables.CPUMinerAPITCPPort) -v -l $($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Week}
- API = "nheq"
- Port = $Variables.CPUMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/opt-yespower.ps1 b/Miners/opt-yespower.ps1
deleted file mode 100644
index 32f099e2ec..0000000000
--- a/Miners/opt-yespower.ps1
+++ /dev/null
@@ -1,69 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\CPU-JayDDeeYespower\cpuminer-sse42.exe"
-$Uri = "https://github.com/bubasik/cpuminer-opt-yespower/releases/download/v3.8.8.3/cpuminer-opt-cryply-yespower-ver2.zip"
-
-$Commands = [PSCustomObject]@{
- # "allium" = "" #Allium
- #"bitcore" = "" #Bitcore
- #"blake2s" = "" #Blake2s
- #"blakecoin" = "" #Blakecoin
- #"vanilla" = "" #BlakeVanilla
- #"c11" = "" #C11
- # "cryptonight" = "" #CryptoNight
- #"cryptonightv7" = "" #cryptonightv7
- #"decred" = "" #Decred
- #"equihash" = "" #Equihash
- #"ethash" = "" #Ethash
- #"groestl" = "" #Groestl
- # "hmq1725" = "" #HMQ1725
- # "hodl" = "" #Hodl
- #"jha" = "" #JHA
- #"keccak" = "" #Keccak
- #"lbry" = "" #Lbry
- #"lyra2v2" = "" #Lyra2RE2
- # "lyra2z" = "" #Lyra2z
- # "m7m" = "" #m7m
- #"myr-gr" = "" #MyriadGroestl
- #"neoscrypt" = "" #NeoScrypt
- #"nist5" = "" #Nist5
- #"pascal" = "" #Pascal
- #"sib" = "" #Sib
- #"skein" = "" #Skein
- #"skunk" = "" #Skunk
- #"timetravel" = "" #Timetravel
- #"tribus" = "" #Tribus
- #"veltor" = "" #Veltor
- #"x11evo" = "" #X11evo
- #"x17" = "" #X17
- # "x16r" = "" #X16r
- # "yescrypt" = "" #Yescrypt
- "yespower" = "" #Yespower
- # "yescryptr16" = "" #YescryptR16
- # "yescryptr32" = "" #YescryptR32
-}
-
-$Name = Get-Item $MyInvocation.MyCommand.Path | Select-Object -ExpandProperty BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
-
- switch ($_) {
- "hodl" {$ThreadCount = $Variables.ProcessorCount}
- default {$ThreadCount = $Variables.ProcessorCount - 2}
- }
-
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "CPU"
- Path = $Path
- Arguments = "--cpu-affinity AAAA -q -t $($ThreadCount) -b $($Variables.CPUMinerAPITCPPort) -a $_ -o $($Pools.($Algo).Protocol)://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Week}
- API = "Ccminer"
- Port = $Variables.CPUMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/progpow.ps1 b/Miners/progpow.ps1
deleted file mode 100644
index 94c3e7ccc6..0000000000
--- a/Miners/progpow.ps1
+++ /dev/null
@@ -1,27 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-progpowminer016\progpowminer-cuda.exe"
-$Uri = "https://nemosminer.com/data/optional/progpowminer0.16-FinalCuda10.7z"
-
-$Commands = [PSCustomObject]@{
- "progpow" = "" # (fastest)
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--cuda-devices $($Config.SelGPUDSTM) --api-port -$($Variables.NVIDIAMinerAPITCPPort) -U -P stratum://$($Pools.($Algo).User):x@$($Pools.($Algo).Host):$($Pools.($Algo).Port)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day}
- API = "ethminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Miners/xmrstak.ps1 b/Miners/xmrstak.ps1
deleted file mode 100644
index c7407446dd..0000000000
--- a/Miners/xmrstak.ps1
+++ /dev/null
@@ -1,63 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\CryptoNight-FireIce2104\xmr-stak.exe"
-$Uri = "https://github.com/fireice-uk/xmr-stak/releases/download/2.10.4/xmr-stak-win64-2.10.4.7z"
-
-$Name = Get-Item $MyInvocation.MyCommand.Path | Select-Object -ExpandProperty BaseName
-$Port = 3335
-
-$Commands = [PSCustomObject]@{
- #"cryptonight_heavy" = "" # CryptoNight-Heavy(cryptodredge faster)
- #"cryptonight_lite" = "" # CryptoNight-Lite
- #"cryptonight_v7" = "" # CryptoNightV7(cryptodredge faster)
- #"cryptonight_v8" = "" # CryptoNightV8
- # "monero" = "" # Monero(v8)
- #"cryptonight_r" = "" #Cryptonight_r (XMRig faster + lower fee)
-}
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
-
- $Algorithm_Norm = Get-Algorithm($_)
-
- ([PSCustomObject]@{
- pool_list = @([PSCustomObject]@{
- pool_address = "$($Pools.$Algorithm_Norm.Host):$($Pools.$Algorithm_Norm.Port)"
- wallet_address = "$($Pools.$Algorithm_Norm.User)"
- pool_password = "$($Pools.$Algorithm_Norm.Pass)"
- use_nicehash = $true
- use_tls = $Pools.$Algorithm_Norm.SSL
- tls_fingerprint = ""
- pool_weight = 1
- rig_id = ""
- }
- )
- currency = if ($Pools.$Algorithm_Norm.Info) {"$($Pools.$Algorithm_Norm.Info -replace '^monero$', 'monero7' -replace '^aeon$', 'aeon7')"} else {"$_"}
- call_timeout = 10
- retry_time = 10
- giveup_limit = 0
- verbose_level = 3
- print_motd = $true
- h_print_time = 60
- aes_override = $null
- use_slow_memory = "warn"
- tls_secure_algo = $true
- daemon_mode = $false
- flush_stdout = $false
- output_file = ""
- httpd_port = $Port
- http_login = ""
- http_pass = ""
- prefer_ipv4 = $true
- } | ConvertTo-Json -Depth 10
- ) -replace "^{" -replace "}$" | Set-Content "$(Split-Path $Path)\$($Pools.$Algorithm_Norm.Name)_$($Algorithm_Norm)_$($Pools.$Algorithm_Norm.User)_Nvidia.txt" -Force -ErrorAction SilentlyContinue
-
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "-C $($Pools.$Algorithm_Norm.Name)_$($Algorithm_Norm)_$($Pools.$Algorithm_Norm.User)_Nvidia.txt --noAMD --noCPU -i $($Port)"
- HashRates = [PSCustomObject]@{$Algorithm_Norm = $Stats."$($Name)_$($Algorithm_Norm)_HashRate".Day * .98} # substract 2% devfee
- API = "fireice"
- Port = $Port
- URI = $Uri
- }
-}
diff --git a/NemosMiner.bat b/NemosMiner.bat
index 84c8b36f8a..703175fe32 100644
--- a/NemosMiner.bat
+++ b/NemosMiner.bat
@@ -1 +1,21 @@
-C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -version 5.0 -executionpolicy bypass -windowstyle maximized -command ".\NemosMiner.ps1 -ConfigFile '.\Config\config.json'"
+@echo off
+
+
+WHERE /q PWSH.exe
+
+IF ERRORLEVEL 1 (
+
+ echo Powershell 6 or later is required. Cannot continue.
+ pause
+
+) ELSE (
+
+ if not "%GPU_FORCE_64BIT_PTR%"=="1" (setx GPU_FORCE_64BIT_PTR 1) > nul
+ if not "%GPU_MAX_HEAP_SIZE%"=="100" (setx GPU_MAX_HEAP_SIZE 100) > nul
+ if not "%GPU_USE_SYNC_OBJECTS%"=="1" (setx GPU_USE_SYNC_OBJECTS 1) > nul
+ if not "%GPU_MAX_ALLOC_PERCENT%"=="100" (setx GPU_MAX_ALLOC_PERCENT 100) > nul
+ if not "%GPU_SINGLE_ALLOC_PERCENT%"=="100" (setx GPU_SINGLE_ALLOC_PERCENT 100) > nul
+ if not "%CUDA_DEVICE_ORDER%"=="PCI_BUS_ID" (setx CUDA_DEVICE_ORDER PCI_BUS_ID) > nul
+
+ PWSH -executionpolicy bypass -windowstyle maximized -command ".\NemosMiner.ps1 -ConfigFile '.\Config\config.json'"
+)
diff --git a/NemosMiner.ps1 b/NemosMiner.ps1
index 029ccf4357..c653481472 100644
--- a/NemosMiner.ps1
+++ b/NemosMiner.ps1
@@ -1,1574 +1,1695 @@
-<#
-Copyright (c) 2018-2019 Nemo and MrPlus
-NemosMiner is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-NemosMiner is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-#>
-
-<#
-Product: NemosMiner
-File: NemosMiner.ps1
-version: 3.8.0.0
-version date: 16 May 2019
-#>
-
-param(
- [Parameter(Mandatory = $false)]
- [String]$Wallet = "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE",
- [Parameter(Mandatory = $false)]
- [String]$UserName = "nemo",
- [Parameter(Mandatory = $false)]
- [String]$WorkerName = "ID=NemosMiner-v3.8.0.0",
- [Parameter(Mandatory = $false)]
- [Int]$API_ID = 0,
- [Parameter(Mandatory = $false)]
- [String]$API_Key = "",
- [Parameter(Mandatory = $false)]
- [Int]$Interval = 120, #seconds before between cycles after the first has passed
- [Parameter(Mandatory = $false)]
- [Int]$FirstInterval = 30, #seconds of the first cycle of activated or started first time miner
- [Parameter(Mandatory = $false)]
- [Int]$StatsInterval = 180, #seconds of current active to gather hashrate if not gathered yet
- [Parameter(Mandatory = $false)]
- [String]$Location = "US", #europe/us/asia
- [Parameter(Mandatory = $false)]
- [Switch]$SSL = $false,
- [Parameter(Mandatory = $false)]
- [Array]$Type = "nvidia", #AMD/NVIDIA/CPU
- [Parameter(Mandatory = $false)]
- [String]$SelGPUDSTM = "0 1",
- [Parameter(Mandatory = $false)]
- [String]$SelGPUCC = "0,1",
- [Parameter(Mandatory = $false)]
- [Array]$Algorithm = $null, #i.e. Ethash,Equihash,Cryptonight ect.
- [Parameter(Mandatory = $false)]
- [Array]$MinerName = $null,
- [Parameter(Mandatory = $false)]
- [Array]$PoolName = $null,
- [Parameter(Mandatory = $false)]
- [Array]$Currency = ("USD"), #i.e. GBP,USD,AUD,NZD ect.
- [Parameter(Mandatory = $false)]
- [Array]$Passwordcurrency = ("BTC"), #i.e. BTC,LTC,ZEC,ETH ect.
- [Parameter(Mandatory = $false)]
- [Int]$Donate = 5, #Minutes per Day
- [Parameter(Mandatory = $false)]
- [String]$Proxy = "", #i.e http://192.0.0.1:8080
- [Parameter(Mandatory = $false)]
- [Int]$Delay = 3, #seconds before opening each miner
- [Parameter(Mandatory = $false)]
- [Int]$GPUCount = 1, # Number of GPU on the system
- [Parameter(Mandatory = $false)]
- [Int]$ActiveMinerGainPct = 5, # percent of advantage that active miner has over candidates in term of profit
- [Parameter(Mandatory = $false)]
- [Float]$MarginOfError = 0, #0.4, # knowledge about the past wont help us to predict the future so don't pretend that Week_Fluctuation means something real
- [Parameter(Mandatory = $false)]
- [String]$UIStyle = "Light", # Light or Full. Defines level of info displayed
- [Parameter(Mandatory = $false)]
- [Bool]$TrackEarnings = $True, # Display earnings information
- [Parameter(Mandatory = $false)]
- [Bool]$Autoupdate = $true, # Autoupdate
- [Parameter(Mandatory = $false)]
- [String]$ConfigFile = ".\Config\config.json"
-)
-
-
-. .\include.ps1
-. .\Core.ps1
-
-@"
-NemosMiner
-Copyright (c) 2018-2019 Nemo and MrPlus
-This is free software, and you are welcome to redistribute it
-under certain conditions.
-https://github.com/nemosminer/NemosMiner/blob/master/LICENSE
-"@
-Write-Host -F Yellow " Copyright and license notices must be preserved."
-@"
-"@
-
-$Global:Config = [hashtable]::Synchronized(@{})
-$Global:Variables = [hashtable]::Synchronized(@{})
-$Global:Variables | Add-Member -Force -MemberType ScriptProperty -Name 'StatusText' -Value { $this._StatusText; $This._StatusText = @() } -SecondValue { If (!$this._StatusText) {$this._StatusText = @()}; $this._StatusText += $args[0]; $Variables | Add-Member -Force @{RefreshNeeded = $True} }
-$Global:Variables | Add-Member -Force @{Started = $False}
-$Global:Variables | Add-Member -Force @{Paused = $False}
-$Global:Variables | Add-Member -Force @{RestartCycle = $False}
-
-Function Form_Load {
- $MainForm.Text = "$($Variables.CurrentProduct) $($Variables.CurrentVersion)"
- $LabelBTCD.Text = "$($Variables.CurrentProduct) $($Variables.CurrentVersion)"
- $MainForm.Number = 0
- $TimerUI.Interval = 50
- $TimerUI.Add_Tick( {
- trap {
- $PSItem.ToString() | out-file .\logs\excepUI.txt -Append
- }
- $TimerUI.Stop()
- # If something (pause button, idle timer) has set the RestartCycle flag, stop and start mining to switch modes immediately
- If ($Variables.RestartCycle) {
- $Variables.RestartCycle = $False
- Stop-Mining
- Start-Mining
- }
- If ($Variables.RefreshNeeded -and $Variables.Started) {
- If (!$Variables.EndLoop) {Update-Status($Variables.StatusText)}
- # $TimerUI.Interval = 1
-
- Start-ChildJobs
-
- $Variables.EarningsTrackerJobs | ? {$_.state -eq "Running"} | foreach {
- $EarnTrack = $_ | Receive-Job
- If ($EarnTrack) {
- $Variables.EarningsPool = (($EarnTrack[($EarnTrack.Count - 1)]).Pool)
- # $Variables.Earnings.$Variables.EarningsPool = $EarnTrack[($EarnTrack.Count - 1)]
- $Variables.Earnings.(($EarnTrack[($EarnTrack.Count - 1)]).Pool) = $EarnTrack[($EarnTrack.Count - 1)]
- rv EarnTrack
- }
- }
-
- If ((compare -ReferenceObject $CheckedListBoxPools.Items -DifferenceObject ((Get-ChildItem ".\Pools").BaseName | sort -Unique) | ? {$_.SideIndicator -eq "=>"}).InputObject -gt 0) {
- (compare -ReferenceObject $CheckedListBoxPools.Items -DifferenceObject ((Get-ChildItem ".\Pools").BaseName | sort -Unique) | ? {$_.SideIndicator -eq "=>"}).InputObject | % { if ($_ -ne $null) {}$CheckedListBoxPools.Items.AddRange($_)}
- $Config.PoolName | foreach {$CheckedListBoxPools.SetItemChecked($CheckedListBoxPools.Items.IndexOf($_), $True)}
- }
- $Variables | Add-Member -Force @{InCycle = $True}
- # $MainForm.Number+=1
- $MainForm.Text = $Variables.CurrentProduct + " " + $Variables.CurrentVersion + " Runtime " + ("{0:dd\ \d\a\y\s\ hh\:mm}" -f ((get-date) - $Variables.ScriptStartDate)) + " Path: " + (Split-Path $script:MyInvocation.MyCommand.Path)
- $host.UI.RawUI.WindowTitle = $Variables.CurrentProduct + " " + $Variables.CurrentVersion + " Runtime " + ("{0:dd\ \d\a\y\s\ hh\:mm}" -f ((get-date) - $Variables.ScriptStartDate)) + " Path: " + (Split-Path $script:MyInvocation.MyCommand.Path)
-
- $SwitchingDisplayTypes = @()
- $SwitchingPageControls | foreach {if ($_.Checked) {$SwitchingDisplayTypes += $_.Tag}}
- # If (Test-Path ".\Logs\switching.log"){$SwitchingArray = [System.Collections.ArrayList]@(Import-Csv ".\Logs\switching.log" | ? {$_.Type -in $SwitchingDisplayTypes} | Select -Last 13)}
- # If (Test-Path ".\Logs\switching.log"){$SwitchingArray = [System.Collections.ArrayList]@(Import-Csv ".\Logs\switching.log" | ? {$_.Type -in $SwitchingDisplayTypes} | Select -Last 13)}
- If (Test-Path ".\Logs\switching.log") {$SwitchingArray = [System.Collections.ArrayList]@(@((get-content ".\Logs\switching.log" -First 1) , (get-content ".\logs\switching.log" -last 50)) | ConvertFrom-Csv | ? {$_.Type -in $SwitchingDisplayTypes} | Select -Last 13)}
- $SwitchingDGV.DataSource = $SwitchingArray
-
- If ($Variables.Earnings -and $Config.TrackEarnings) {
- $DisplayEarnings = [System.Collections.ArrayList]@($Variables.Earnings.Values | select @(
- @{Name = "Pool"; Expression = {$_.Pool}},
- @{Name = "Trust"; Expression = {"{0:P0}" -f $_.TrustLevel}},
- @{Name = "Balance"; Expression = {$_.Balance}},
- # @{Name="Unpaid";Expression={$_.total_unpaid}},
- @{Name = "BTC/D"; Expression = {"{0:N8}" -f ($_.BTCD)}},
- @{Name = "mBTC/D"; Expression = {"{0:N3}" -f ($_.BTCD * 1000)}},
- @{Name = "Est. Pay Date"; Expression = {if ($_.EstimatedPayDate -is 'DateTime') {$_.EstimatedPayDate.ToShortDateString()} else {$_.EstimatedPayDate}}},
- @{Name = "PaymentThreshold"; Expression = {"$($_.PaymentThreshold) ($('{0:P0}' -f $($_.Balance / $_.PaymentThreshold)))"}},
- @{Name = "Wallet"; Expression = {$_.Wallet}}
- ) | Sort "BTC/D" -Descending)
- $EarningsDGV.DataSource = [System.Collections.ArrayList]@($DisplayEarnings)
- $EarningsDGV.ClearSelection()
- }
-
- If ($Variables.Miners) {
- $DisplayEstimations = [System.Collections.ArrayList]@($Variables.Miners | Select @(
- @{Name = "Miner"; Expression = {$_.Name}},
- @{Name = "Algorithm"; Expression = {$_.HashRates.PSObject.Properties.Name}},
- @{Name = "Speed"; Expression = {$_.HashRates.PSObject.Properties.Value | ForEach {if ($_ -ne $null) {"$($_ | ConvertTo-Hash)/s"}else {"Benchmarking"}}}},
- @{Name = "mBTC/Day"; Expression = {$_.Profits.PSObject.Properties.Value * 1000 | ForEach {if ($_ -ne $null) {$_.ToString("N3")}else {"Benchmarking"}}}},
- @{Name = "BTC/Day"; Expression = {$_.Profits.PSObject.Properties.Value | ForEach {if ($_ -ne $null) {$_.ToString("N5")}else {"Benchmarking"}}}},
- @{Name = "BTC/GH/Day"; Expression = {$_.Pools.PSObject.Properties.Value.Price | ForEach {($_ * 1000000000).ToString("N5")}}},
- @{Name = "Pool"; Expression = {$_.Pools.PSObject.Properties.Value | ForEach {"$($_.Name)-$($_.Info)"}}}
- ) | sort "mBTC/Day" -Descending)
- $EstimationsDGV.DataSource = [System.Collections.ArrayList]@($DisplayEstimations)
- }
- $EstimationsDGV.ClearSelection()
-
- $SwitchingDGV.ClearSelection()
-
- If ($Variables.Workers -and $Config.ShowWorkerStatus) {
- $DisplayWorkers = [System.Collections.ArrayList]@($Variables.Workers | select @(
- @{Name = "Worker"; Expression = {$_.worker}},
- @{Name = "Status"; Expression = {$_.status}},
- @{Name = "Last Seen"; Expression = {$_.timesincelastreport}},
- @{Name = "Version"; Expression = {$_.version}},
- @{Name = "Est. BTC/Day"; Expression = {[decimal]$_.profit}},
- @{Name = "Miner"; Expression = {$_.data.name -join ','}},
- @{Name = "Pool"; Expression = {$_.data.pool -join ','}},
- @{Name = "Algo"; Expression = {$_.data.algorithm -join ','}},
- @{Name = "Speed"; Expression = {if ($_.data.currentspeed) {($_.data.currentspeed | ConvertTo-Hash) -join ','} else {""}}},
- @{Name = "Benchmark Speed"; Expression = {if ($_.data.estimatedspeed) {($_.data.estimatedspeed | ConvertTo-Hash) -join ','} else {""}}}
- ) | Sort "Worker Name")
- $WorkersDGV.DataSource = [System.Collections.ArrayList]@($DisplayWorkers)
-
- # Set row color
- $WorkersDGV.Rows | ForEach-Object {
- if ($_.DataBoundItem.Status -eq "Offline") {
- $_.DefaultCellStyle.Backcolor = [System.Drawing.Color]::FromArgb(255, 213, 142, 176)
- }
- elseif ($_.DataBoundItem.Status -eq "Paused") {
- $_.DefaultCellStyle.Backcolor = [System.Drawing.Color]::FromArgb(255, 247, 252, 168)
- }
- elseif ($_.DataBoundItem.Status -eq "Running") {
- $_.DefaultCellStyle.Backcolor = [System.Drawing.Color]::FromArgb(255, 127, 191, 144)
- }
- else {
- $_.DefaultCellStyle.Backcolor = [System.Drawing.Color]::FromArgb(255, 255, 255, 255)
- }
- }
-
- $WorkersDGV.ClearSelection()
- $LabelMonitoringWorkers.text = "Worker Status - Updated $($Variables.WorkersLastUpdated.ToString())"
- }
-
- If ($Variables.ActiveMinerPrograms) {
- $RunningMinersDGV.DataSource = [System.Collections.ArrayList]@($Variables.ActiveMinerPrograms | ? {$_.Status -eq "Running"} | select Type, Algorithms, Name, @{Name = "HashRate"; Expression = {"$($_.HashRate | ConvertTo-Hash)/s"}}, @{Name = "Stratum"; Expression = {"$($_.Arguments.Split(' ') | ?{$_ -match 'stratum'})"}} | sort Type)
- $RunningMinersDGV.ClearSelection()
-
- [Array] $processRunning = $Variables.ActiveMinerPrograms | Where { $_.Status -eq "Running" }
- If ($ProcessRunning -eq $null) {
- # Update-Status("No miner running")
- }
- }
- $LabelBTCPrice.text = If ($Variables.Rates.$Currency -gt 0) {"BTC/$($Config.Currency) $($Variables.Rates.($Config.Currency))"}
- $Variables | Add-Member -Force @{InCycle = $False}
-
- If ($Variables.EndLoop) {
- If ($Variables.Earnings.Values -ne $Null) {
- $LabelBTCD.Text = "Avg: " + ("{0:N6}" -f ($Variables.Earnings.Values | measure -Property BTCD -Sum).sum) + " BTC/D | " + ("{0:N3}" -f (($Variables.Earnings.Values | measure -Property BTCD -Sum).sum * 1000)) + " mBTC/D"
-
- $LabelEarningsDetails.Lines = @()
- # If ((($Variables.Earnings.Values | measure -Property Growth1 -Sum).sum*1000*24) -lt ((($Variables.Earnings.Values | measure -Property BTCD -Sum).sum*1000)*0.999)) {
- # $LabelEarningsDetails.ForeColor = "Red" } else { $LabelEarningsDetails.ForeColor = "Green" }
- $TrendSign = switch ([Math]::Round((($Variables.Earnings.Values | measure -Property Growth1 -Sum).sum * 1000 * 24), 3) - [Math]::Round((($Variables.Earnings.Values | measure -Property BTCD -Sum).sum * 1000), 3)) {
- {$_ -eq 0}
- {"="}
- {$_ -gt 0}
- {">"}
- {$_ -lt 0}
- {"<"}
- }
- $LabelEarningsDetails.Lines += "Last 1h: " + ("{0:N3}" -f (($Variables.Earnings.Values | measure -Property Growth1 -Sum).sum * 1000 * 24)) + " mBTC/D " + $TrendSign
- $TrendSign = switch ([Math]::Round((($Variables.Earnings.Values | measure -Property Growth6 -Sum).sum * 1000 * 4), 3) - [Math]::Round((($Variables.Earnings.Values | measure -Property BTCD -Sum).sum * 1000), 3)) {
- {$_ -eq 0}
- {"="}
- {$_ -gt 0}
- {">"}
- {$_ -lt 0}
- {"<"}
- }
- $LabelEarningsDetails.Lines += "Last 6h: " + ("{0:N3}" -f (($Variables.Earnings.Values | measure -Property Growth6 -Sum).sum * 1000 * 4)) + " mBTC/D " + $TrendSign
- $TrendSign = switch ([Math]::Round((($Variables.Earnings.Values | measure -Property Growth24 -Sum).sum * 1000), 3) - [Math]::Round((($Variables.Earnings.Values | measure -Property BTCD -Sum).sum * 1000), 3)) {
- {$_ -eq 0}
- {"="}
- {$_ -gt 0}
- {">"}
- {$_ -lt 0}
- {"<"}
- }
- $LabelEarningsDetails.Lines += "Last 24h: " + ("{0:N3}" -f (($Variables.Earnings.Values | measure -Property Growth24 -Sum).sum * 1000)) + " mBTC/D " + $TrendSign
- rv TrendSign
- }
- else {
- $LabelBTCD.Text = "Waiting data from pools."
- $LabelEarningsDetails.Lines = @()
- }
-
- if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
- if (!(IsLoaded(".\Core.ps1"))) {. .\Core.ps1; RegisterLoaded(".\Core.ps1")}
-
- $Variables | Add-Member -Force @{CurrentProduct = (Get-Content .\Version.json | ConvertFrom-Json).Product}
- $Variables | Add-Member -Force @{CurrentVersion = [Version](Get-Content .\Version.json | ConvertFrom-Json).Version}
- $Variables | Add-Member -Force @{CurrentVersionAutoUpdated = (Get-Content .\Version.json | ConvertFrom-Json).AutoUpdated.Value}
- if ((Get-Content .\Version.json | ConvertFrom-Json).AutoUpdated -and $LabelNotifications.Lines[$LabelNotifications.Lines.Count - 1] -ne "Auto Updated on $($Variables.CurrentVersionAutoUpdated)") {
- $LabelNotifications.ForeColor = "Green"
- Update-Notifications("Running $($Variables.CurrentProduct) Version $([Version]$Variables.CurrentVersion)")
- Update-Notifications("Auto Updated on $($Variables.CurrentVersionAutoUpdated)")
- }
-
- #Display mining information
- if ($host.UI.RawUI.KeyAvailable) {
- $KeyPressed = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown,IncludeKeyUp"); sleep -Milliseconds 300; $host.UI.RawUI.FlushInputBuffer()
- If ($KeyPressed.KeyDown) {
- Switch ($KeyPressed.Character) {
- "s" {if ($Config.UIStyle -eq "Light") {$Config.UIStyle = "Full"}else {$Config.UIStyle = "Light"}}
- "e" {$Config.TrackEarnings = -not $Config.TrackEarnings}
- }
- }
- }
- Clear-Host
- [Array] $processesIdle = $Variables.ActiveMinerPrograms | Where { $_.Status -eq "Idle" }
- IF ($Config.UIStyle -eq "Full") {
- if ($processesIdle.Count -gt 0) {
- Write-Host "Idle: " $processesIdle.Count
- $processesIdle | Sort {if ($_.Process -eq $null) {(Get-Date)}else {$_.Process.ExitTime}} | Format-Table -Wrap (
- @{Label = "Speed"; Expression = {$_.HashRate | ForEach {"$($_ | ConvertTo-Hash)/s"}}; Align = 'right'},
- @{Label = "Exited"; Expression = {"{0:dd}:{0:hh}:{0:mm}" -f $(if ($_.Process -eq $null) {(0)}else {(Get-Date) - $_.Process.ExitTime}) }},
- @{Label = "Active"; Expression = {"{0:dd}:{0:hh}:{0:mm}" -f $(if ($_.Process -eq $null) {$_.Active}else {if ($_.Process.ExitTime -gt $_.Process.StartTime) {($_.Active + ($_.Process.ExitTime - $_.Process.StartTime))}else {($_.Active + ((Get-Date) - $_.Process.StartTime))}})}},
- @{Label = "Cnt"; Expression = {Switch ($_.Activated) {0 {"Never"} 1 {"Once"} Default {"$_"}}}},
- @{Label = "Command"; Expression = {"$($_.Path.TrimStart((Convert-Path ".\"))) $($_.Arguments)"}}
- ) | Out-Host
- }
- }
- Write-Host " 1BTC = $($Variables.Rates.($Config.Currency)) $($Config.Currency)"
- # Get and display earnings stats
- If ($Variables.Earnings -and $Config.TrackEarnings) {
- # $Variables.Earnings.Values | select Pool,Wallet,Balance,AvgDailyGrowth,EstimatedPayDate,TrustLevel | ft *
- $Variables.Earnings.Values | foreach {
- Write-Host "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" -F DarkGray
- Write-Host "Pool name " -NoNewline; Write-Host $_.pool -F Yellow
- Write-Host "Wallet " -NoNewline; Write-Host $_.Wallet -F Yellow
- Write-Host "Balance " $_.balance ("{0:P0}" -f ($_.balance / $_.PaymentThreshold))
- Write-Host "Trust Level " ("{0:P0}" -f $_.TrustLevel) -NoNewline; Write-Host -F darkgray " Avg based on [" ("{0:dd\ \d\a\y\s\ hh\:mm}" -f ($_.Date - $_.StartTime))"]"
- Write-Host "Average BTC/H" -NoNewline; Write-Host " BTC = " -F DarkGray -NoNewline; Write-Host ("{0:N8}" -f $_.AvgHourlyGrowth) "| mBTC =" ("{0:N3}" -f ($_.AvgHourlyGrowth * 1000))
- Write-Host "Average BTC/D" -NoNewline; Write-Host " BTC =" ("{0:N8}" -f ($_.BTCD)) "| mBTC =" ("{0:N3}" -f ($_.BTCD * 1000)) -F Yellow
- Write-Host "Estimated Pay Date " $_.EstimatedPayDate ">" $_.PaymentThreshold "BTC"
- # Write-Host "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" -F DarkGray
- }
- }
- Write-Host "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" -F DarkGray
- if ($Variables.Miners | ? {$_.HashRates.PSObject.Properties.Value -eq $null}) {$Config.UIStyle = "Full"}
- IF ($Config.UIStyle -eq "Full") {
-
- $Variables.Miners | Sort -Descending Type, Profit | Format-Table -GroupBy Type (
- @{Label = "Miner"; Expression = {$_.Name}},
- @{Label = "Algorithm"; Expression = {$_.HashRates.PSObject.Properties.Name}},
- @{Label = "Speed"; Expression = {$_.HashRates.PSObject.Properties.Value | ForEach {if ($_ -ne $null) {"$($_ | ConvertTo-Hash)/s"}else {"Benchmarking"}}}; Align = 'right'},
- @{Label = "mBTC/Day"; Expression = {$_.Profits.PSObject.Properties.Value * 1000 | ForEach {if ($_ -ne $null) {$_.ToString("N3")}else {"Benchmarking"}}}; Align = 'right'},
- @{Label = "BTC/Day"; Expression = {$_.Profits.PSObject.Properties.Value | ForEach {if ($_ -ne $null) {$_.ToString("N5")}else {"Benchmarking"}}}; Align = 'right'},
- @{Label = "$($Config.Currency)/Day"; Expression = {$_.Profits.PSObject.Properties.Value | ForEach {if ($_ -ne $null) {($_ * $Variables.Rates.($Config.Currency)).ToString("N3")}else {"Benchmarking"}}}; Align = 'right'},
- @{Label = "BTC/GH/Day"; Expression = {$_.Pools.PSObject.Properties.Value.Price | ForEach {($_ * 1000000000).ToString("N5")}}; Align = 'right'},
- @{Label = "Pool"; Expression = {$_.Pools.PSObject.Properties.Value | ForEach {"$($_.Name)-$($_.Info)"}}}
- ) | Out-Host
- #Display active miners list
- [Array] $processRunning = $Variables.ActiveMinerPrograms | Where { $_.Status -eq "Running" }
- Write-Host "Running:"
- $processRunning | Sort {if ($_.Process -eq $null) {[DateTime]0}else {$_.Process.StartTime}} | Format-Table -Wrap (
- @{Label = "Speed"; Expression = {$_.HashRate | ForEach {"$($_ | ConvertTo-Hash)/s"}}; Align = 'right'},
- @{Label = "Started"; Expression = {"{0:dd}:{0:hh}:{0:mm}" -f $(if ($_.Process -eq $null) {(0)}else {(Get-Date) - $_.Process.StartTime}) }},
- @{Label = "Active"; Expression = {"{0:dd}:{0:hh}:{0:mm}" -f $(if ($_.Process -eq $null) {$_.Active}else {if ($_.Process.ExitTime -gt $_.Process.StartTime) {($_.Active + ($_.Process.ExitTime - $_.Process.StartTime))}else {($_.Active + ((Get-Date) - $_.Process.StartTime))}})}},
- @{Label = "Cnt"; Expression = {Switch ($_.Activated) {0 {"Never"} 1 {"Once"} Default {"$_"}}}},
- @{Label = "Command"; Expression = {"$($_.Path.TrimStart((Convert-Path ".\"))) $($_.Arguments)"}}
- ) | Out-Host
- [Array] $processesFailed = $Variables.ActiveMinerPrograms | Where { $_.Status -eq "Failed" }
- if ($processesFailed.Count -gt 0) {
- Write-Host -ForegroundColor Red "Failed: " $processesFailed.Count
- $processesFailed | Sort {if ($_.Process -eq $null) {[DateTime]0}else {$_.Process.StartTime}} | Format-Table -Wrap (
- @{Label = "Speed"; Expression = {$_.HashRate | ForEach {"$($_ | ConvertTo-Hash)/s"}}; Align = 'right'},
- @{Label = "Exited"; Expression = {"{0:dd}:{0:hh}:{0:mm}" -f $(if ($_.Process -eq $null) {(0)}else {(Get-Date) - $_.Process.ExitTime}) }},
- @{Label = "Active"; Expression = {"{0:dd}:{0:hh}:{0:mm}" -f $(if ($_.Process -eq $null) {$_.Active}else {if ($_.Process.ExitTime -gt $_.Process.StartTime) {($_.Active + ($_.Process.ExitTime - $_.Process.StartTime))}else {($_.Active + ((Get-Date) - $_.Process.StartTime))}})}},
- @{Label = "Cnt"; Expression = {Switch ($_.Activated) {0 {"Never"} 1 {"Once"} Default {"$_"}}}},
- @{Label = "Command"; Expression = {"$($_.Path.TrimStart((Convert-Path ".\"))) $($_.Arguments)"}}
- ) | Out-Host
- }
- Write-Host "--------------------------------------------------------------------------------"
-
- }
- else {
- [Array] $processRunning = $Variables.ActiveMinerPrograms | Where { $_.Status -eq "Running" }
- Write-Host "Running:"
- $processRunning | Sort {if ($_.Process -eq $null) {[DateTime]0}else {$_.Process.StartTime}} | Format-Table -Wrap (
- @{Label = "Speed"; Expression = {$_.HashRate | ForEach {"$($_ | ConvertTo-Hash)/s"}}; Align = 'right'},
- @{Label = "Started"; Expression = {"{0:dd}:{0:hh}:{0:mm}" -f $(if ($_.Process -eq $null) {(0)}else {(Get-Date) - $_.Process.StartTime}) }},
- @{Label = "Active"; Expression = {"{0:dd}:{0:hh}:{0:mm}" -f $(if ($_.Process -eq $null) {$_.Active}else {if ($_.Process.ExitTime -gt $_.Process.StartTime) {($_.Active + ($_.Process.ExitTime - $_.Process.StartTime))}else {($_.Active + ((Get-Date) - $_.Process.StartTime))}})}},
- @{Label = "Cnt"; Expression = {Switch ($_.Activated) {0 {"Never"} 1 {"Once"} Default {"$_"}}}},
- @{Label = "Command"; Expression = {"$($_.Path.TrimStart((Convert-Path ".\"))) $($_.Arguments)"}}
- ) | Out-Host
- Write-Host "--------------------------------------------------------------------------------"
- }
- Write-Host -ForegroundColor Yellow "Last Refresh: $(Get-Date)"
- Update-Status($Variables.StatusText)
- }
- if (Test-Path ".\EndUIRefresh.ps1") {Invoke-Expression (Get-Content ".\EndUIRefresh.ps1" -Raw)}
-
- $Variables.RefreshNeeded = $False
- }
- else {
- Sleep -Milliseconds 1
- }
- $TimerUI.Start()
- })
- $TimerUI.Start()
-}
-
-Function CheckedListBoxPools_Click ($Control) {
- $Config | Add-Member -Force @{$Control.Tag = $Control.CheckedItems}
-}
-
-Function PrepareWriteConfig {
- If ($Config -eq $null) {$Config = [hashtable]::Synchronized(@{})
- }
- $Config | Add-Member -Force @{$TBAddress.Tag = $TBAddress.Text}
- $Config | Add-Member -Force @{$TBWorkerName.Tag = $TBWorkerName.Text}
- $ConfigPageControls | ? {(($_.gettype()).Name -eq "CheckBox")} | foreach {$Config | Add-Member -Force @{$_.Tag = $_.Checked}}
- $ConfigPageControls | ? {(($_.gettype()).Name -eq "TextBox")} | foreach {$Config | Add-Member -Force @{$_.Tag = $_.Text}}
- $MonitoringSettingsControls | ? {(($_.gettype()).Name -eq "CheckBox")} | foreach {$Config | Add-Member -Force @{$_.Tag = $_.Checked}}
- $MonitoringSettingsControls | ? {(($_.gettype()).Name -eq "TextBox")} | foreach {$Config | Add-Member -Force @{$_.Tag = $_.Text}}
- $ConfigPageControls | ? {(($_.gettype()).Name -eq "TextBox") -and ($_.Tag -eq "GPUCount")} | foreach {
- $Config | Add-Member -Force @{$_.Tag = [Int]$_.Text}
- If ($CheckBoxDisableGPU0.checked -and [Int]$_.Text -gt 1) {$FirstGPU = 1}else {$FirstGPU = 0}
- $Config | Add-Member -Force @{SelGPUCC = (($FirstGPU..($_.Text - 1)) -join ",")}
- $Config | Add-Member -Force @{SelGPUDSTM = (($FirstGPU..($_.Text - 1)) -join " ")}
- }
- $ConfigPageControls | ? {(($_.gettype()).Name -eq "TextBox") -and ($_.Tag -eq "Algorithm")} | foreach {
- $Config | Add-Member -Force @{$_.Tag = @($_.Text -split ",")}
- }
- $ConfigPageControls | ? {(($_.gettype()).Name -eq "TextBox") -and ($_.Tag -in @("Donate", "Interval", "ActiveMinerGainPct", "IdleSec"))} | foreach {
- $Config | Add-Member -Force @{$_.Tag = [Int]$_.Text}
- }
- $Config | Add-Member -Force @{$CheckedListBoxPools.Tag = $CheckedListBoxPools.CheckedItems}
- Write-Config -ConfigFile $ConfigFile -Config $Config
- $MainForm.Refresh
- # [windows.forms.messagebox]::show("Please restart NemosMiner",'Config saved','ok','Information') | out-null
-}
-
-Add-Type -AssemblyName System.Windows.Forms
-[System.Windows.Forms.Application]::EnableVisualStyles()
-
-# If (Test-Path ".\Logs\switching.log"){$log=Import-Csv ".\Logs\switching.log" | Select -Last 14}
-# $SwitchingArray = [System.Collections.ArrayList]@($Log)
-If (Test-Path ".\Logs\switching.log") {$SwitchingArray = [System.Collections.ArrayList]@(Import-Csv ".\Logs\switching.log" | Select -Last 14)}
-
-$MainForm = New-Object system.Windows.Forms.Form
-$NMIcon = New-Object system.drawing.icon (".\NM.ICO")
-$MainForm.Icon = $NMIcon
-$MainForm.ClientSize = '740,450' # best to keep under 800,600
-$MainForm.text = "Form"
-$MainForm.TopMost = $false
-$MainForm.FormBorderStyle = 'Fixed3D'
-$MainForm.MaximizeBox = $false
-
-$MainForm.add_Shown( {
- # Check if new version is available
- Update-Status("Checking version")
- try {
- $Version = Invoke-WebRequest "https://nemosminer.com/data/version.json" -TimeoutSec 15 -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
- }
- catch {$Version = Get-content ".\Config\version.json" | Convertfrom-json}
- If ($Version -ne $null) {$Version | ConvertTo-json | Out-File ".\Config\version.json"}
- If ($Version.Product -eq $Variables.CurrentProduct -and [Version]$version.Version -gt $Variables.CurrentVersion -and $Version.Update) {
- Update-Status("Version $($version.Version) available. (You are running $($Variables.CurrentVersion))")
- If ([version](GetNVIDIADriverVersion) -ge [Version]$Version.MinNVIDIADriverVersion) {
- $LabelNotifications.ForeColor = "Green"
- $LabelNotifications.Lines += "Version $([Version]$version.Version) available"
- $LabelNotifications.Lines += $version.Message
- If ($Config.Autoupdate -and ! $Config.ManualConfig) {Autoupdate}
- }
- else {
- Update-Status("Version $($version.Version) available. Please update NVIDIA driver. Will not AutoUpdate")
- $LabelNotifications.ForeColor = "Red"
- $LabelNotifications.Lines += "Driver update required. Version $([Version]$version.Version) available"
- }
- }
-
- # TimerCheckVersion
- $TimerCheckVersion = New-Object System.Windows.Forms.Timer
- $TimerCheckVersion.Enabled = $true
- $TimerCheckVersion.Interval = 1440 * 60 * 1000
- $TimerCheckVersion.Add_Tick( {
- Update-Status("Checking version")
- try {
- $Version = Invoke-WebRequest "https://nemosminer.com/data/version.json" -TimeoutSec 15 -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
- }
- catch {$Version = Get-content ".\Config\version.json" | Convertfrom-json}
- If ($Version -ne $null) {$Version | ConvertTo-json | Out-File ".\Config\version.json"}
- If ($Version.Product -eq $Variables.CurrentProduct -and [Version]$version.Version -gt $Variables.CurrentVersion -and $Version.Update) {
- If ([version](GetNVIDIADriverVersion) -ge [Version]$Version.MinNVIDIADriverVersion) {
- $LabelNotifications.ForeColor = "Green"
- $LabelNotifications.Lines += "Version $([Version]$version.Version) available"
- $LabelNotifications.Lines += $version.Message
- If ($Config.Autoupdate -and ! $Config.ManualConfig) {Autoupdate}
- }
- else {
- Update-Status("Version $($version.Version) available. Please update NVIDIA driver. Will not AutoUpdate")
- $LabelNotifications.ForeColor = "Red"
- $LabelNotifications.Lines += "Driver update required. Version $([Version]$version.Version) available"
- }
-
- }
- })
- # Detects GPU count if 0 or Null in config
- If ($Config.GPUCount -eq $null -or $Config.GPUCount -lt 1) {
- If ($Config -eq $null) {$Config = [hashtable]::Synchronized(@{})
- }
- $Config | Add-Member -Force @{GPUCount = DetectGPUCount}
- $TBGPUCount.Text = $Config.GPUCount
- PrepareWriteConfig
- }
- # Start on load if Autostart
- If ($Config.Autostart) {
- If ($Config.StartPaused) {
- $Variables.Paused = $True
- $ButtonPause.Text = "Mine"
- }
- $ButtonStart.PerformClick()
- }
- If ($Config.StartGUIMinimized) {$MainForm.WindowState = [System.Windows.Forms.FormWindowState]::Minimized}
- If ($Config.HideConsole) {$null = $ShowWindow::ShowWindowAsync($ConsoleHandle, 0)}
- })
-
-$MainForm.Add_FormClosing( {
- $TimerUI.Stop()
- Update-Status("Stopping jobs and miner")
-
- if ($Variables.EarningsTrackerJobs) {$Variables.EarningsTrackerJobs | % {$_ | Stop-Job | Remove-Job}}
- if ($Variables.BrainJobs) {$Variables.BrainJobs | % {$_ | Stop-Job | Remove-Job}}
-
- If ($Variables.ActiveMinerPrograms) {
- $Variables.ActiveMinerPrograms | ForEach {
- [Array]$filtered = ($BestMiners_Combo | Where Path -EQ $_.Path | Where Arguments -EQ $_.Arguments)
- if ($filtered.Count -eq 0) {
- if ($_.Process -eq $null) {
- $_.Status = "Failed"
- }
- elseif ($_.Process.HasExited -eq $false) {
- $_.Active += (Get-Date) - $_.Process.StartTime
- $_.Process.CloseMainWindow() | Out-Null
- Sleep 1
- # simply "Kill with power"
- Stop-Process $_.Process -Force | Out-Null
- # Try to kill any process with the same path, in case it is still running but the process handle is incorrect
- $KillPath = $_.Path
- Get-Process | Where-Object {$_.Path -eq $KillPath} | Stop-Process -Force
- Write-Host -ForegroundColor Yellow "closing miner"
- Sleep 1
- $_.Status = "Idle"
- }
- }
- }
- }
-
- # $Result = $powershell.EndInvoke($Variables.CycleRunspaceHandle)
- if ($CycleRunspace) {$CycleRunspace.Close()}
- if ($powershell) {$powershell.Dispose()}
- if ($IdleRunspace) {$IdleRunspace.Close()}
- if ($idlePowershell) {$idlePowershell.Dispose()}
- })
-
-$Config = Load-Config -ConfigFile $ConfigFile
-
-$Config | Add-Member -Force -MemberType ScriptProperty -Name "PoolsConfig" -Value {
- If (Test-Path ".\Config\PoolsConfig.json") {
- get-content ".\Config\PoolsConfig.json" | ConvertFrom-json
- }
- else {
- [PSCustomObject]@{default = [PSCustomObject]@{
- Wallet = "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE"
- UserName = "nemo"
- WorkerName = "NemosMinerNoCfg"
- PricePenaltyFactor = 1
- }
- }
- }
-}
-
-$MainForm | Add-Member -Name "Config" -Value $Config -MemberType NoteProperty -Force
-
-$SelGPUDSTM = $Config.SelGPUDSTM
-$SelGPUCC = $Config.SelGPUCC
-$MainForm | Add-Member -Name "Variables" -Value $Variables -MemberType NoteProperty -Force
-
-$Variables | Add-Member -Force @{CurrentProduct = (Get-Content .\Version.json | ConvertFrom-Json).Product}
-$Variables | Add-Member -Force @{CurrentVersion = [Version](Get-Content .\Version.json | ConvertFrom-Json).Version}
-$Variables | Add-Member -Force @{CurrentVersionAutoUpdated = (Get-Content .\Version.json | ConvertFrom-Json).AutoUpdated.Value}
-$Variables.StatusText = "Idle"
-$TabControl = New-object System.Windows.Forms.TabControl
-$RunPage = New-Object System.Windows.Forms.TabPage
-$RunPage.Text = "Run"
-$SwitchingPage = New-Object System.Windows.Forms.TabPage
-$SwitchingPage.Text = "Switching"
-$ConfigPage = New-Object System.Windows.Forms.TabPage
-$ConfigPage.Text = "Config"
-$MonitoringPage = New-Object System.Windows.Forms.TabPage
-$MonitoringPage.Text = "Monitoring"
-$EstimationsPage = New-Object System.Windows.Forms.TabPage
-$EstimationsPage.Text = "Benchmarks"
-
-$tabControl.DataBindings.DefaultDataSourceUpdateMode = 0
-$tabControl.Location = New-Object System.Drawing.Point(10, 91)
-$tabControl.Name = "tabControl"
-$tabControl.width = 720
-$tabControl.height = 359
-$MainForm.Controls.Add($tabControl)
-$TabControl.Controls.AddRange(@($RunPage, $SwitchingPage, $ConfigPage, $MonitoringPage, $EstimationsPage))
-# Form Controls
-$MainFormControls = @()
-
-$LabelEarningsDetails = New-Object system.Windows.Forms.TextBox
-$LabelEarningsDetails.Tag = ""
-$LabelEarningsDetails.MultiLine = $true
-$LabelEarningsDetails.text = ""
-$LabelEarningsDetails.AutoSize = $false
-$LabelEarningsDetails.width = 200 #382
-$LabelEarningsDetails.height = 47 #62
-$LabelEarningsDetails.location = New-Object System.Drawing.Point(10, 2)
-$LabelEarningsDetails.Font = 'lucida console,10'
-$LabelEarningsDetails.BorderStyle = 'None'
-$LabelEarningsDetails.BackColor = [System.Drawing.SystemColors]::Control
-$LabelEarningsDetails.ForeColor = "Green"
-$LabelEarningsDetails.Visible = $True
-# $TBNotifications.TextAlign = "Right"
-$MainFormControls += $LabelEarningsDetails
-
-$LabelBTCD = New-Object system.Windows.Forms.Label
-$LabelBTCD.text = "BTC/D"
-$LabelBTCD.AutoSize = $False
-$LabelBTCD.width = 390
-$LabelBTCD.height = 35
-$LabelBTCD.location = New-Object System.Drawing.Point(330, 2)
-$LabelBTCD.Font = 'Microsoft Sans Serif,14'
-$LabelBTCD.TextAlign = "MiddleRight"
-$LabelBTCD.ForeColor = "Green"
-$LabelBTCD.Backcolor = "Transparent"
-# $LabelBTCD.BorderStyle = 'FixedSingle'
-$MainFormControls += $LabelBTCD
-
-$LabelBTCPrice = New-Object system.Windows.Forms.Label
-$LabelBTCPrice.text = If ($Variables.Rates.$Currency -gt 0) {"BTC/$($Config.Currency) $($Variables.Rates.$Currency)"}
-$LabelBTCPrice.AutoSize = $false
-$LabelBTCPrice.width = 400
-$LabelBTCPrice.height = 20
-$LabelBTCPrice.location = New-Object System.Drawing.Point(630, 39)
-$LabelBTCPrice.Font = 'Microsoft Sans Serif,8'
-# $LabelBTCPrice.ForeColor = "Gray"
-$MainFormControls += $LabelBTCPrice
-
-$ButtonPause = New-Object system.Windows.Forms.Button
-$ButtonPause.text = "Pause"
-$ButtonPause.width = 60
-$ButtonPause.height = 30
-$ButtonPause.location = New-Object System.Drawing.Point(610, 62)
-$ButtonPause.Font = 'Microsoft Sans Serif,10'
-$ButtonPause.Visible = $False
-$MainFormControls += $ButtonPause
-
-$ButtonStart = New-Object system.Windows.Forms.Button
-$ButtonStart.text = "Start"
-$ButtonStart.width = 60
-$ButtonStart.height = 30
-$ButtonStart.location = New-Object System.Drawing.Point(670, 62)
-$ButtonStart.Font = 'Microsoft Sans Serif,10'
-$MainFormControls += $ButtonStart
-
-$LabelNotifications = New-Object system.Windows.Forms.TextBox
-$LabelNotifications.Tag = ""
-$LabelNotifications.MultiLine = $true
-# $TBNotifications.Scrollbars = "Vertical"
-$LabelNotifications.text = ""
-$LabelNotifications.AutoSize = $false
-$LabelNotifications.width = 280
-$LabelNotifications.height = 18
-$LabelNotifications.location = New-Object System.Drawing.Point(345, 49)
-$LabelNotifications.Font = 'Microsoft Sans Serif,10'
-$LabelNotifications.BorderStyle = 'None'
-$LabelNotifications.BackColor = [System.Drawing.SystemColors]::Control
-$LabelNotifications.Visible = $True
-# $TBNotifications.TextAlign = "Right"
-$MainFormControls += $LabelNotifications
-
-$LabelGitHub = New-Object System.Windows.Forms.LinkLabel
-# $LabelGitHub.Location = New-Object System.Drawing.Size(415,39)
-# $LabelGitHub.Size = New-Object System.Drawing.Size(160,18)
-$LabelGitHub.Location = New-Object System.Drawing.Size(10, 49)
-$LabelGitHub.Size = New-Object System.Drawing.Size(200, 18)
-$LabelGitHub.LinkColor = "BLUE"
-$LabelGitHub.ActiveLinkColor = "RED"
-$LabelGitHub.Text = "NemosMiner on GitHub"
-$LabelGitHub.add_Click( {[system.Diagnostics.Process]::start("https://github.com/nemosminer/NemosMiner/releases")})
-$MainFormControls += $LabelGitHub
-
-$LabelCopyright = New-Object System.Windows.Forms.LinkLabel
-$LabelCopyright.Location = New-Object System.Drawing.Size(400, 72)
-$LabelCopyright.Size = New-Object System.Drawing.Size(220, 18)
-$LabelCopyright.LinkColor = "BLUE"
-$LabelCopyright.ActiveLinkColor = "RED"
-$LabelCopyright.Text = "Copyright (c) 2018-2019 Nemo and MrPlus"
-$LabelCopyright.add_Click( {[system.Diagnostics.Process]::start("https://github.com/nemosminer/NemosMiner/blob/master/LICENSE")})
-$MainFormControls += $LabelCopyright
-
-$LabelAddress = New-Object system.Windows.Forms.Label
-$LabelAddress.text = "Wallet Address"
-$LabelAddress.AutoSize = $false
-$LabelAddress.width = 100
-$LabelAddress.height = 20
-$LabelAddress.location = New-Object System.Drawing.Point(10, 68)
-$LabelAddress.Font = 'Microsoft Sans Serif,10'
-$MainFormControls += $LabelAddress
-
-$TBAddress = New-Object system.Windows.Forms.TextBox
-$TBAddress.Tag = "Wallet"
-$TBAddress.MultiLine = $False
-# $TBAddress.Scrollbars = "Vertical"
-$TBAddress.text = $Config.Wallet
-$TBAddress.AutoSize = $false
-$TBAddress.width = 280
-$TBAddress.height = 20
-$TBAddress.location = New-Object System.Drawing.Point(112, 68)
-$TBAddress.Font = 'Microsoft Sans Serif,10'
-# $TBAddress.TextAlign = "Right"
-$MainFormControls += $TBAddress
-
-# Run Page Controls
-$RunPageControls = @()
-
-$LabelStatus = New-Object system.Windows.Forms.TextBox
-$LabelStatus.MultiLine = $true
-$LabelStatus.Scrollbars = "Vertical"
-$LabelStatus.text = ""
-$LabelStatus.AutoSize = $true
-$LabelStatus.width = 712
-$LabelStatus.height = 50
-$LabelStatus.location = New-Object System.Drawing.Point(2, 2)
-$LabelStatus.Font = 'Microsoft Sans Serif,10'
-$RunPageControls += $LabelStatus
-
-$LabelEarnings = New-Object system.Windows.Forms.Label
-$LabelEarnings.text = "Earnings Tracker"
-$LabelEarnings.AutoSize = $false
-$LabelEarnings.width = 300
-$LabelEarnings.height = 20
-$LabelEarnings.location = New-Object System.Drawing.Point(2, 54)
-$LabelEarnings.Font = 'Microsoft Sans Serif,10'
-$RunPageControls += $LabelEarnings
-
-$EarningsDGV = New-Object system.Windows.Forms.DataGridView
-$EarningsDGV.width = 712
-# $EarningsDGV.height = 305
-$EarningsDGV.height = 170
-$EarningsDGV.location = New-Object System.Drawing.Point(2, 74)
-$EarningsDGV.DataBindings.DefaultDataSourceUpdateMode = 0
-$EarningsDGV.AutoSizeColumnsMode = "Fill"
-$EarningsDGV.RowHeadersVisible = $False
-$RunPageControls += $EarningsDGV
-
-$LabelRunningMiners = New-Object system.Windows.Forms.Label
-$LabelRunningMiners.text = "Running Miners"
-$LabelRunningMiners.AutoSize = $false
-$LabelRunningMiners.width = 300
-$LabelRunningMiners.height = 20
-$LabelRunningMiners.location = New-Object System.Drawing.Point(2, 246)
-$LabelRunningMiners.Font = 'Microsoft Sans Serif,10'
-$RunPageControls += $LabelRunningMiners
-
-$RunningMinersDGV = New-Object system.Windows.Forms.DataGridView
-$RunningMinersDGV.width = 712
-# $EarningsDGV.height = 305
-$RunningMinersDGV.height = 95
-$RunningMinersDGV.location = New-Object System.Drawing.Point(2, 266)
-$RunningMinersDGV.DataBindings.DefaultDataSourceUpdateMode = 0
-$RunningMinersDGV.AutoSizeColumnsMode = "Fill"
-$RunningMinersDGV.RowHeadersVisible = $False
-$RunPageControls += $RunningMinersDGV
-
-# Switching Page Controls
-$SwitchingPageControls = @()
-
-$CheckShowSwitchingCPU = New-Object system.Windows.Forms.CheckBox
-$CheckShowSwitchingCPU.Tag = "CPU"
-$CheckShowSwitchingCPU.text = "CPU"
-$CheckShowSwitchingCPU.AutoSize = $false
-$CheckShowSwitchingCPU.width = 60
-$CheckShowSwitchingCPU.height = 20
-$CheckShowSwitchingCPU.location = New-Object System.Drawing.Point(2, 2)
-$CheckShowSwitchingCPU.Font = 'Microsoft Sans Serif,10'
-$CheckShowSwitchingCPU.Checked = ("CPU" -in $Config.Type)
-$SwitchingPageControls += $CheckShowSwitchingCPU
-
-$CheckShowSwitchingCPU | foreach {$_.Add_Click( {CheckBoxSwitching_Click($This)})}
-
-$CheckShowSwitchingNVIDIA = New-Object system.Windows.Forms.CheckBox
-$CheckShowSwitchingNVIDIA.Tag = "NVIDIA"
-$CheckShowSwitchingNVIDIA.text = "NVIDIA"
-$CheckShowSwitchingNVIDIA.AutoSize = $false
-$CheckShowSwitchingNVIDIA.width = 100
-$CheckShowSwitchingNVIDIA.height = 20
-$CheckShowSwitchingNVIDIA.location = New-Object System.Drawing.Point(62, 2)
-$CheckShowSwitchingNVIDIA.Font = 'Microsoft Sans Serif,10'
-$CheckShowSwitchingNVIDIA.Checked = ("NVIDIA" -in $Config.Type)
-$SwitchingPageControls += $CheckShowSwitchingNVIDIA
-
-$CheckShowSwitchingNVIDIA | foreach {$_.Add_Click( {CheckBoxSwitching_Click($This)})}
-
-Function CheckBoxSwitching_Click {
- $SwitchingDisplayTypes = @()
- $SwitchingPageControls | foreach {if ($_.Checked) {$SwitchingDisplayTypes += $_.Tag}}
- # If (Test-Path ".\Logs\switching.log"){$log=Import-Csv ".\Logs\switching.log" | ? {$_.Type -in $SwitchingDisplayTypes} | Select -Last 13}
- # $SwitchingArray = [System.Collections.ArrayList]@($Log)
- # If (Test-Path ".\Logs\switching.log"){$SwitchingArray = [System.Collections.ArrayList]@(Import-Csv ".\Logs\switching.log" | ? {$_.Type -in $SwitchingDisplayTypes} | Select -Last 13)}
- If (Test-Path ".\Logs\switching.log") {$SwitchingArray = [System.Collections.ArrayList]@(@((get-content ".\Logs\switching.log" -First 1) , (get-content ".\logs\switching.log" -last 50)) | ConvertFrom-Csv | ? {$_.Type -in $SwitchingDisplayTypes} | Select -Last 13)}
- $SwitchingDGV.DataSource = $SwitchingArray
-}
-
-
-$SwitchingDGV = New-Object system.Windows.Forms.DataGridView
-$SwitchingDGV.width = 712
-$SwitchingDGV.height = 333
-$SwitchingDGV.location = New-Object System.Drawing.Point(2, 22)
-$SwitchingDGV.DataBindings.DefaultDataSourceUpdateMode = 0
-$SwitchingDGV.AutoSizeColumnsMode = "Fill"
-$SwitchingDGV.RowHeadersVisible = $False
-$SwitchingDGV.DataSource = $SwitchingArray
-$SwitchingPageControls += $SwitchingDGV
-
-# Estimations Page Controls
-$EstimationsDGV = New-Object system.Windows.Forms.DataGridView
-$EstimationsDGV.width = 712
-$EstimationsDGV.height = 350
-$EstimationsDGV.location = New-Object System.Drawing.Point(2, 2)
-$EstimationsDGV.DataBindings.DefaultDataSourceUpdateMode = 0
-$EstimationsDGV.AutoSizeColumnsMode = "Fill"
-$EstimationsDGV.RowHeadersVisible = $False
-
-# Config Page Controls
-$ConfigPageControls = @()
-
-$LabelWorkerName = New-Object system.Windows.Forms.Label
-$LabelWorkerName.text = "Worker Name"
-$LabelWorkerName.AutoSize = $false
-$LabelWorkerName.width = 120
-$LabelWorkerName.height = 20
-$LabelWorkerName.location = New-Object System.Drawing.Point(2, 2)
-$LabelWorkerName.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $LabelWorkerName
-
-$TBWorkerName = New-Object system.Windows.Forms.TextBox
-$TBWorkerName.Tag = "WorkerName"
-$TBWorkerName.MultiLine = $False
-# $TBWorkerName.Scrollbars = "Vertical"
-$TBWorkerName.text = $Config.WorkerName
-$TBWorkerName.AutoSize = $false
-$TBWorkerName.width = 300
-$TBWorkerName.height = 20
-$TBWorkerName.location = New-Object System.Drawing.Point(122, 2)
-$TBWorkerName.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $TBWorkerName
-
-
-$LabelUserName = New-Object system.Windows.Forms.Label
-$LabelUserName.text = "MPH UserName"
-$LabelUserName.AutoSize = $false
-$LabelUserName.width = 120
-$LabelUserName.height = 20
-$LabelUserName.location = New-Object System.Drawing.Point(2, 24)
-$LabelUserName.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $LabelUserName
-
-$TBUserName = New-Object system.Windows.Forms.TextBox
-$TBUserName.Tag = "UserName"
-$TBUserName.MultiLine = $False
-# $TBUserName.Scrollbars = "Vertical"
-$TBUserName.text = $Config.UserName
-$TBUserName.AutoSize = $false
-$TBUserName.width = 300
-$TBUserName.height = 20
-$TBUserName.location = New-Object System.Drawing.Point(122, 24)
-$TBUserName.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $TBUserName
-
-$LabelInterval = New-Object system.Windows.Forms.Label
-$LabelInterval.text = "Interval"
-$LabelInterval.AutoSize = $false
-$LabelInterval.width = 120
-$LabelInterval.height = 20
-$LabelInterval.location = New-Object System.Drawing.Point(2, 46)
-$LabelInterval.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $LabelInterval
-
-$TBInterval = New-Object system.Windows.Forms.TextBox
-$TBInterval.Tag = "Interval"
-$TBInterval.MultiLine = $False
-# $TBWorkerName.Scrollbars = "Vertical"
-$TBInterval.text = $Config.Interval
-$TBInterval.AutoSize = $false
-$TBInterval.width = 300
-$TBInterval.height = 20
-$TBInterval.location = New-Object System.Drawing.Point(122, 46)
-$TBInterval.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $TBInterval
-
-$LabelLocation = New-Object system.Windows.Forms.Label
-$LabelLocation.text = "Location"
-$LabelLocation.AutoSize = $false
-$LabelLocation.width = 120
-$LabelLocation.height = 20
-$LabelLocation.location = New-Object System.Drawing.Point(2, 68)
-$LabelLocation.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $LabelLocation
-
-$TBLocation = New-Object system.Windows.Forms.TextBox
-$TBLocation.Tag = "Location"
-$TBLocation.MultiLine = $False
-# $TBLocation.Scrollbars = "Vertical"
-$TBLocation.text = $Config.Location
-$TBLocation.AutoSize = $false
-$TBLocation.width = 300
-$TBLocation.height = 20
-$TBLocation.location = New-Object System.Drawing.Point(122, 68)
-$TBLocation.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $TBLocation
-
-$LabelGPUCount = New-Object system.Windows.Forms.Label
-$LabelGPUCount.text = "GPU Count"
-$LabelGPUCount.AutoSize = $false
-$LabelGPUCount.width = 120
-$LabelGPUCount.height = 20
-$LabelGPUCount.location = New-Object System.Drawing.Point(2, 90)
-$LabelGPUCount.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $LabelGPUCount
-
-$TBGPUCount = New-Object system.Windows.Forms.TextBox
-$TBGPUCount.Tag = "GPUCount"
-$TBGPUCount.MultiLine = $False
-# $TBGPUCount.Scrollbars = "Vertical"
-$TBGPUCount.text = $Config.GPUCount
-$TBGPUCount.AutoSize = $false
-$TBGPUCount.width = 50
-$TBGPUCount.height = 20
-$TBGPUCount.location = New-Object System.Drawing.Point(122, 90)
-$TBGPUCount.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $TBGPUCount
-
-$CheckBoxDisableGPU0 = New-Object system.Windows.Forms.CheckBox
-$CheckBoxDisableGPU0.Tag = "DisableGPU0"
-$CheckBoxDisableGPU0.text = "Disable GPU0"
-$CheckBoxDisableGPU0.AutoSize = $false
-$CheckBoxDisableGPU0.width = 140
-$CheckBoxDisableGPU0.height = 20
-$CheckBoxDisableGPU0.location = New-Object System.Drawing.Point(177, 90)
-$CheckBoxDisableGPU0.Font = 'Microsoft Sans Serif,10'
-$CheckBoxDisableGPU0.Checked = $Config.DisableGPU0
-$ConfigPageControls += $CheckBoxDisableGPU0
-
-$ButtonDetectGPU = New-Object system.Windows.Forms.Button
-$ButtonDetectGPU.text = "Detect GPU"
-$ButtonDetectGPU.width = 100
-$ButtonDetectGPU.height = 20
-$ButtonDetectGPU.location = New-Object System.Drawing.Point(320, 90)
-$ButtonDetectGPU.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $ButtonDetectGPU
-
-$ButtonDetectGPU.Add_Click( {$TBGPUCount.text = DetectGPUCount})
-
-$LabelAlgos = New-Object system.Windows.Forms.Label
-$LabelAlgos.text = "Algorithm"
-$LabelAlgos.AutoSize = $false
-$LabelAlgos.width = 120
-$LabelAlgos.height = 20
-$LabelAlgos.location = New-Object System.Drawing.Point(2, 112)
-$LabelAlgos.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $LabelAlgos
-
-$TBAlgos = New-Object system.Windows.Forms.TextBox
-$TBAlgos.Tag = "Algorithm"
-$TBAlgos.MultiLine = $False
-# $TBAlgos.Scrollbars = "Vertical"
-$TBAlgos.text = $Config.Algorithm -Join ","
-$TBAlgos.AutoSize = $false
-$TBAlgos.width = 300
-$TBAlgos.height = 20
-$TBAlgos.location = New-Object System.Drawing.Point(122, 112)
-$TBAlgos.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $TBAlgos
-
-$LabelCurrency = New-Object system.Windows.Forms.Label
-$LabelCurrency.text = "Currency"
-$LabelCurrency.AutoSize = $false
-$LabelCurrency.width = 120
-$LabelCurrency.height = 20
-$LabelCurrency.location = New-Object System.Drawing.Point(2, 134)
-$LabelCurrency.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $LabelCurrency
-
-$TBCurrency = New-Object system.Windows.Forms.TextBox
-$TBCurrency.Tag = "Currency"
-$TBCurrency.MultiLine = $False
-# $TBCurrency.Scrollbars = "Vertical"
-$TBCurrency.text = $Config.Currency
-$TBCurrency.AutoSize = $false
-$TBCurrency.width = 300
-$TBCurrency.height = 20
-$TBCurrency.location = New-Object System.Drawing.Point(122, 134)
-$TBCurrency.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $TBCurrency
-
-$LabelPwdCurrency = New-Object system.Windows.Forms.Label
-$LabelPwdCurrency.text = "Pwd Currency"
-$LabelPwdCurrency.AutoSize = $false
-$LabelPwdCurrency.width = 120
-$LabelPwdCurrency.height = 20
-$LabelPwdCurrency.location = New-Object System.Drawing.Point(2, 156)
-$LabelPwdCurrency.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $LabelPwdCurrency
-
-$TBPwdCurrency = New-Object system.Windows.Forms.TextBox
-$TBPwdCurrency.Tag = "Passwordcurrency"
-$TBPwdCurrency.MultiLine = $False
-# $TBPwdCurrency.Scrollbars = "Vertical"
-$TBPwdCurrency.text = $Config.Passwordcurrency
-$TBPwdCurrency.AutoSize = $false
-$TBPwdCurrency.width = 300
-$TBPwdCurrency.height = 20
-$TBPwdCurrency.location = New-Object System.Drawing.Point(122, 156)
-$TBPwdCurrency.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $TBPwdCurrency
-
-$LabelDonate = New-Object system.Windows.Forms.Label
-$LabelDonate.text = "Donate (min)"
-$LabelDonate.AutoSize = $false
-$LabelDonate.width = 120
-$LabelDonate.height = 20
-$LabelDonate.location = New-Object System.Drawing.Point(2, 178)
-$LabelDonate.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $LabelDonate
-
-$TBDonate = New-Object system.Windows.Forms.TextBox
-$TBDonate.Tag = "Donate"
-$TBDonate.MultiLine = $False
-# $TBDonate.Scrollbars = "Vertical"
-$TBDonate.text = $Config.Donate
-$TBDonate.AutoSize = $false
-$TBDonate.width = 300
-$TBDonate.height = 20
-$TBDonate.location = New-Object System.Drawing.Point(122, 178)
-$TBDonate.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $TBDonate
-
-$LabelProxy = New-Object system.Windows.Forms.Label
-$LabelProxy.text = "Proxy"
-$LabelProxy.AutoSize = $false
-$LabelProxy.width = 120
-$LabelProxy.height = 20
-$LabelProxy.location = New-Object System.Drawing.Point(2, 202)
-$LabelProxy.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $LabelProxy
-
-$TBProxy = New-Object system.Windows.Forms.TextBox
-$TBProxy.Tag = "Proxy"
-$TBProxy.MultiLine = $False
-# $TBProxy.Scrollbars = "Vertical"
-$TBProxy.text = $Config.Proxy
-$TBProxy.AutoSize = $false
-$TBProxy.width = 300
-$TBProxy.height = 20
-$TBProxy.location = New-Object System.Drawing.Point(122, 202)
-$TBProxy.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $TBProxy
-
-$LabelActiveMinerGainPct = New-Object system.Windows.Forms.Label
-$LabelActiveMinerGainPct.text = "ActiveMinerGain%"
-$LabelActiveMinerGainPct.AutoSize = $false
-$LabelActiveMinerGainPct.width = 120
-$LabelActiveMinerGainPct.height = 20
-$LabelActiveMinerGainPct.location = New-Object System.Drawing.Point(2, 224)
-$LabelActiveMinerGainPct.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $LabelActiveMinerGainPct
-
-$TBActiveMinerGainPct = New-Object system.Windows.Forms.TextBox
-$TBActiveMinerGainPct.Tag = "ActiveMinerGainPct"
-$TBActiveMinerGainPct.MultiLine = $False
-# $TBActiveMinerGainPct.Scrollbars = "Vertical"
-$TBActiveMinerGainPct.text = $Config.ActiveMinerGainPct
-$TBActiveMinerGainPct.AutoSize = $false
-$TBActiveMinerGainPct.width = 300
-$TBActiveMinerGainPct.height = 20
-$TBActiveMinerGainPct.location = New-Object System.Drawing.Point(122, 224)
-$TBActiveMinerGainPct.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $TBActiveMinerGainPct
-
-$LabelMPHAPIKey = New-Object system.Windows.Forms.Label
-$LabelMPHAPIKey.text = "MPH API Key"
-$LabelMPHAPIKey.AutoSize = $false
-$LabelMPHAPIKey.width = 120
-$LabelMPHAPIKey.height = 20
-$LabelMPHAPIKey.location = New-Object System.Drawing.Point(2, 246)
-$LabelMPHAPIKey.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $LabelMPHAPIKey
-
-$TBMPHAPIKey = New-Object system.Windows.Forms.TextBox
-$TBMPHAPIKey.Tag = "APIKEY"
-$TBMPHAPIKey.MultiLine = $False
-$TBMPHAPIKey.text = $Config.APIKEY
-$TBMPHAPIKey.AutoSize = $false
-$TBMPHAPIKey.width = 300
-$TBMPHAPIKey.height = 20
-$TBMPHAPIKey.location = New-Object System.Drawing.Point(122, 246)
-$TBMPHAPIKey.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $TBMPHAPIKey
-
-$LabelMinersTypes = New-Object system.Windows.Forms.Label
-$LabelMinersTypes.text = "Miners Types"
-$LabelMinersTypes.AutoSize = $false
-$LabelMinersTypes.width = 120
-$LabelMinersTypes.height = 20
-$LabelMinersTypes.location = New-Object System.Drawing.Point(2, 268)
-$LabelMinersTypes.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $LabelMinersTypes
-
-$CheckBoxMinerTypeCPU = New-Object system.Windows.Forms.CheckBox
-$CheckBoxMinerTypeCPU.Tag = "TypeCPU"
-$CheckBoxMinerTypeCPU.text = "CPU"
-$CheckBoxMinerTypeCPU.AutoSize = $false
-$CheckBoxMinerTypeCPU.width = 60
-$CheckBoxMinerTypeCPU.height = 20
-$CheckBoxMinerTypeCPU.location = New-Object System.Drawing.Point(124, 268)
-$CheckBoxMinerTypeCPU.Font = 'Microsoft Sans Serif,10'
-$CheckBoxMinerTypeCPU.Checked = ($CheckBoxMinerTypeCPU.text -in $Config.Type)
-$ConfigPageControls += $CheckBoxMinerTypeCPU
-
-$CheckBoxMinerTypeCPU.Add_Click( {
- If ($This.checked -and $This.Text -notin $Config.Type) {
- [Array]$Config.Type += $This.Text
- # If ($Variables."$($This.Text)MinerAPITCPPort" -eq $Null){
- If ($Variables."$($This.Text)MinerAPITCPPort" -eq $Null -or ($Variables.ActiveMinerPrograms | ? {$_.Status -eq "Running" -and $_.Type -eq $This.Text}) -eq $null) {
- # Find available TCP Ports
- $StartPort = 4068
- Update-Status("Finding available TCP Port for $($This.Text)")
- $Port = Get-FreeTcpPort($StartPort)
- $Variables | Add-Member -Force @{"$($This.Text)MinerAPITCPPort" = $Port}
- Update-Status("Miners API Port: $($Port)")
- $StartPort = $Port + 1
- }
- }
- else {$Config.Type = @($Config.Type | ? {$_ -ne $This.Text})}
- })
-
-$CheckBoxMinerTypeNVIDIA = New-Object system.Windows.Forms.CheckBox
-$CheckBoxMinerTypeNVIDIA.Tag = "TypeNVIDIA"
-$CheckBoxMinerTypeNVIDIA.text = "NVIDIA"
-$CheckBoxMinerTypeNVIDIA.AutoSize = $false
-$CheckBoxMinerTypeNVIDIA.width = 100
-$CheckBoxMinerTypeNVIDIA.height = 20
-$CheckBoxMinerTypeNVIDIA.location = New-Object System.Drawing.Point(186, 268)
-$CheckBoxMinerTypeNVIDIA.Font = 'Microsoft Sans Serif,10'
-$CheckBoxMinerTypeNVIDIA.Checked = ($CheckBoxMinerTypeNVIDIA.text -in $Config.Type)
-$ConfigPageControls += $CheckBoxMinerTypeNVIDIA
-
-$CheckBoxMinerTypeNVIDIA.Add_Click( {
- If ($This.checked -and $This.Text -notin $Config.Type) {
- [Array]$Config.Type += $This.Text
- If ($Variables."$($This.Text)MinerAPITCPPort" -eq $Null -or ($Variables.ActiveMinerPrograms | ? {$_.Status -eq "Running" -and $_.Type -eq $This.Text}) -eq $null) {
- # Find available TCP Ports
- $StartPort = 4068
- Update-Status("Finding available TCP Port for $($This.Text)")
- $Port = Get-FreeTcpPort($StartPort)
- $Variables | Add-Member -Force @{"$($This.Text)MinerAPITCPPort" = $Port}
- Update-Status("Miners API Port: $($Port)")
- $StartPort = $Port + 1
- }
- }
- else {$Config.Type = @($Config.Type | ? {$_ -ne $This.Text})}
- })
-
-$CheckBoxAutostart = New-Object system.Windows.Forms.CheckBox
-$CheckBoxAutostart.Tag = "Autostart"
-$CheckBoxAutostart.text = "Auto Start"
-$CheckBoxAutostart.AutoSize = $false
-$CheckBoxAutostart.width = 100
-$CheckBoxAutostart.height = 20
-$CheckBoxAutostart.location = New-Object System.Drawing.Point(560, 2)
-$CheckBoxAutostart.Font = 'Microsoft Sans Serif,10'
-$CheckBoxAutostart.Checked = $Config.Autostart
-$ConfigPageControls += $CheckBoxAutostart
-
-$CheckBoxAutoStart.Add_Click( {
- # Disable CheckBoxStartPaused and mine when idle when Auto Start is unchecked
- if ($CheckBoxAutoStart.Checked) {
- $CheckBoxStartPaused.Enabled = $True
- $CheckBoxMineWhenIdle.Enabled = $True
- $TBIdleSec.Enabled = $True
- }
- else {
- $CheckBoxStartPaused.Checked = $False
- $CheckBoxStartPaused.Enabled = $False
- $CheckBoxMineWhenIdle.Checked = $False
- $CheckBoxMineWhenIdle.Enabled = $False
- $TBIdleSec.Enabled = $False
- }
- })
-
-$CheckBoxStartPaused = New-Object system.Windows.Forms.CheckBox
-$CheckBoxStartPaused.Tag = "StartPaused"
-$CheckBoxStartPaused.text = "Pause on Auto Start"
-$CheckBoxStartPaused.AutoSize = $false
-$CheckBoxStartPaused.width = 160
-$CheckBoxStartPaused.height = 20
-$CheckBoxStartPaused.location = New-Object System.Drawing.Point(560, 24)
-$CheckBoxStartPaused.Font = 'Microsoft Sans Serif,10'
-$CheckBoxStartPaused.Checked = $Config.StartPaused
-$CheckBoxStartPaused.Enabled = $CheckBoxAutoStart.Checked
-$ConfigPageControls += $CheckBoxStartPaused
-
-$CheckBoxMineWhenIdle = New-Object system.Windows.Forms.CheckBox
-$CheckBoxMineWhenIdle.Tag = "MineWhenIdle"
-$CheckBoxMineWhenIdle.text = "Mine only when idle"
-$CheckBoxMineWhenIdle.AutoSize = $false
-$CheckBoxMineWhenIdle.width = 160
-$CheckBoxMineWhenIdle.height = 20
-$CheckBoxMineWhenIdle.location = New-Object System.Drawing.Point(560, 46)
-$CheckBoxMineWhenIdle.Font = 'Microsoft Sans Serif,10'
-$CheckBoxMineWhenIdle.Checked = $Config.MineWhenIdle
-$CheckBoxMineWhenIdle.Enabled = $CheckBoxAutoStart.Checked
-$ConfigPageControls += $CheckBoxMineWhenIdle
-
-$TBIdleSec = New-Object system.Windows.Forms.TextBox
-$TBIdleSec.Tag = "IdleSec"
-$TBIdleSec.MultiLine = $False
-$TBIdleSec.text = if ($Config.IdleSec -gt 1) {$Config.IdleSec} else {120}
-$TBIdleSec.AutoSize = $false
-$TBIdleSec.width = 50
-$TBIdleSec.height = 20
-$TBIdleSec.location = New-Object System.Drawing.Point(580, 68)
-$TBIdleSec.Font = 'Microsoft Sans Serif,10'
-$TBIdleSec.Enabled = $CheckBoxAutoStart.Checked
-$ConfigPageControls += $TBIdleSec
-
-$LabelIdleSec = New-Object system.Windows.Forms.Label
-$LabelIdleSec.text = "seconds"
-$LabelIdleSec.AutoSize = $false
-$LabelIdleSec.width = 60
-$LabelIdleSec.height = 20
-$LabelIdleSec.location = New-Object System.Drawing.Point(630, 68)
-$LabelIdleSec.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $LabelIdleSec
-
-$CheckBoxEarningTrackerLogs = New-Object system.Windows.Forms.CheckBox
-$CheckBoxEarningTrackerLogs.Tag = "EnableEarningsTrackerLogs"
-$CheckBoxEarningTrackerLogs.text = "Earnings Tracker Logs"
-$CheckBoxEarningTrackerLogs.AutoSize = $false
-$CheckBoxEarningTrackerLogs.width = 160
-$CheckBoxEarningTrackerLogs.height = 20
-$CheckBoxEarningTrackerLogs.location = New-Object System.Drawing.Point(560, 90)
-$CheckBoxEarningTrackerLogs.Font = 'Microsoft Sans Serif,10'
-$CheckBoxEarningTrackerLogs.Checked = $Config.EnableEarningsTrackerLogs
-$ConfigPageControls += $CheckBoxEarningTrackerLogs
-
-$CheckBoxGUIMinimized = New-Object system.Windows.Forms.CheckBox
-$CheckBoxGUIMinimized.Tag = "StartGUIMinimized"
-$CheckBoxGUIMinimized.text = "Start UI minimized"
-$CheckBoxGUIMinimized.AutoSize = $false
-$CheckBoxGUIMinimized.width = 160
-$CheckBoxGUIMinimized.height = 20
-$CheckBoxGUIMinimized.location = New-Object System.Drawing.Point(560, 112)
-$CheckBoxGUIMinimized.Font = 'Microsoft Sans Serif,10'
-$CheckBoxGUIMinimized.Checked = $Config.StartGUIMinimized
-$ConfigPageControls += $CheckBoxGUIMinimized
-
-$CheckBoxAutoUpdate = New-Object system.Windows.Forms.CheckBox
-$CheckBoxAutoUpdate.Tag = "AutoUpdate"
-$CheckBoxAutoUpdate.text = "Auto Update"
-$CheckBoxAutoUpdate.AutoSize = $true
-$CheckBoxAutoUpdate.width = 100
-$CheckBoxAutoUpdate.height = 20
-$CheckBoxAutoUpdate.location = New-Object System.Drawing.Point(560, 134)
-$CheckBoxAutoUpdate.Font = 'Microsoft Sans Serif,10'
-$CheckBoxAutoUpdate.Checked = $Config.AutoUpdate
-# $CheckBoxAutoUpdate.Enabled = $False
-$ConfigPageControls += $CheckBoxAutoUpdate
-
-$CheckBoxIncludeRegularMiners = New-Object system.Windows.Forms.CheckBox
-$CheckBoxIncludeRegularMiners.Tag = "IncludeRegularMiners"
-$CheckBoxIncludeRegularMiners.text = "Regular Miners"
-$CheckBoxIncludeRegularMiners.AutoSize = $false
-$CheckBoxIncludeRegularMiners.width = 160
-$CheckBoxIncludeRegularMiners.height = 20
-$CheckBoxIncludeRegularMiners.location = New-Object System.Drawing.Point(560, 156)
-$CheckBoxIncludeRegularMiners.Font = 'Microsoft Sans Serif,10'
-$CheckBoxIncludeRegularMiners.Checked = $Config.IncludeRegularMiners
-$ConfigPageControls += $CheckBoxIncludeRegularMiners
-
-$CheckBoxIncludeOptionalMiners = New-Object system.Windows.Forms.CheckBox
-$CheckBoxIncludeOptionalMiners.Tag = "IncludeOptionalMiners"
-$CheckBoxIncludeOptionalMiners.text = "Optional Miners"
-$CheckBoxIncludeOptionalMiners.AutoSize = $false
-$CheckBoxIncludeOptionalMiners.width = 160
-$CheckBoxIncludeOptionalMiners.height = 20
-$CheckBoxIncludeOptionalMiners.location = New-Object System.Drawing.Point(560, 178)
-$CheckBoxIncludeOptionalMiners.Font = 'Microsoft Sans Serif,10'
-$CheckBoxIncludeOptionalMiners.Checked = $Config.IncludeOptionalMiners
-$ConfigPageControls += $CheckBoxIncludeOptionalMiners
-
-$CheckBoxConsole = New-Object system.Windows.Forms.CheckBox
-$CheckBoxConsole.Tag = "HideConsole"
-$CheckBoxConsole.text = "Hide Console"
-$CheckBoxConsole.AutoSize = $false
-$CheckBoxConsole.width = 160
-$CheckBoxConsole.height = 20
-$CheckBoxConsole.location = New-Object System.Drawing.Point(560, 200)
-$CheckBoxConsole.Font = 'Microsoft Sans Serif,10'
-$CheckBoxConsole.Checked = $Config.HideConsole
-$ConfigPageControls += $CheckBoxConsole
-
-$ButtonLoadDefaultPoolsAlgos = New-Object system.Windows.Forms.Button
-$ButtonLoadDefaultPoolsAlgos.text = "Load default algos for selected pools"
-$ButtonLoadDefaultPoolsAlgos.width = 250
-$ButtonLoadDefaultPoolsAlgos.height = 30
-$ButtonLoadDefaultPoolsAlgos.location = New-Object System.Drawing.Point(358, 300)
-$ButtonLoadDefaultPoolsAlgos.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $ButtonLoadDefaultPoolsAlgos
-
-$ButtonLoadDefaultPoolsAlgos.Add_Click( {
- try {
- $PoolsAlgos = Invoke-WebRequest "https://nemosminer.com/data/PoolsAlgos.json" -TimeoutSec 15 -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json; $PoolsAlgos | ConvertTo-json | Out-File ".\Config\PoolsAlgos.json"
- }
- catch { $PoolsAlgos = Get-content ".\Config\PoolsAlgos.json" | Convertfrom-json}
- If ($PoolsAlgos) {
- $PoolsAlgos = $PoolsAlgos.PSObject.Properties | ? {$_.Name -in $Config.PoolName}
- $PoolsAlgos = $PoolsAlgos.Value | sort -Unique
- $TBAlgos.text = $PoolsAlgos -Join ","
- }
- })
-
-$ButtonWriteConfig = New-Object system.Windows.Forms.Button
-$ButtonWriteConfig.text = "Save Config"
-$ButtonWriteConfig.width = 100
-$ButtonWriteConfig.height = 30
-$ButtonWriteConfig.location = New-Object System.Drawing.Point(610, 300)
-$ButtonWriteConfig.Font = 'Microsoft Sans Serif,10'
-$ConfigPageControls += $ButtonWriteConfig
-
-$ButtonWriteConfig.Add_Click( {PrepareWriteConfig})
-
-$LabelPoolsSelect = New-Object system.Windows.Forms.Label
-$LabelPoolsSelect.text = "Do not select multiple variants of the same pool"
-$LabelPoolsSelect.AutoSize = $false
-$LabelPoolsSelect.width = 130
-$LabelPoolsSelect.height = 50
-$LabelPoolsSelect.location = New-Object System.Drawing.Point(427, 2)
-$LabelPoolsSelect.Font = 'Microsoft Sans Serif,10'
-$LabelPoolsSelect.TextAlign = 'MiddleCenter'
-$LabelPoolsSelect.BorderStyle = 'FixedSingle'
-$ConfigPageControls += $LabelPoolsSelect
-
-$CheckedListBoxPools = New-Object System.Windows.Forms.CheckedListBox
-$CheckedListBoxPools.Tag = "PoolName"
-$CheckedListBoxPools.height = 240
-$CheckedListBoxPools.width = 130
-$CheckedListBoxPools.text = "Pools"
-$CheckedListBoxPools.location = New-Object System.Drawing.Point(427, 54)
-$CheckedListBoxPools.CheckOnClick = $True
-$CheckedListBoxPools.BackColor = [System.Drawing.SystemColors]::Control
-$CheckedListBoxPools.Items.Clear()
-$CheckedListBoxPools.Items.AddRange(((Get-ChildItem ".\Pools").BaseName | sort -Unique))
-$CheckedListBoxPools.add_SelectedIndexChanged( {CheckedListBoxPools_Click($This)})
-$Config.PoolName | foreach {$CheckedListBoxPools.SetItemChecked($CheckedListBoxPools.Items.IndexOf($_), $True)}
-
-$ConfigPageControls += $CheckedListBoxPools
-
-# Monitoring Page Controls
-$MonitoringPageControls = @()
-$MonitoringSettingsControls = @()
-
-$LabelMonitoringWorkers = New-Object system.Windows.Forms.Label
-$LabelMonitoringWorkers.text = "Worker Status"
-$LabelMonitoringWorkers.AutoSize = $false
-$LabelMonitoringWorkers.width = 710
-$LabelMonitoringWorkers.height = 20
-$LabelMonitoringWorkers.location = New-Object System.Drawing.Point(2, 4)
-$LabelMonitoringWorkers.Font = 'Microsoft Sans Serif,10'
-$MonitoringPageControls += $LabelMonitoringWorkers
-
-$WorkersDGV = New-Object system.Windows.Forms.DataGridView
-$WorkersDGV.width = 710
-$WorkersDGV.height = 244
-$WorkersDGV.location = New-Object System.Drawing.Point(2, 24)
-$WorkersDGV.DataBindings.DefaultDataSourceUpdateMode = 0
-$WorkersDGV.AutoSizeColumnsMode = "AllCells"
-$WorkersDGV.RowHeadersVisible = $False
-$MonitoringPageControls += $WorkersDGV
-
-$GroupMonitoringSettings = New-Object system.Windows.Forms.GroupBox
-$GroupMonitoringSettings.Height = 60
-$GroupMonitoringSettings.Width = 710
-$GroupMonitoringSettings.Text = "Monitoring Settings"
-$GroupMonitoringSettings.Location = New-Object System.Drawing.Point(1, 272)
-$MonitoringPageControls += $GroupMonitoringSettings
-
-$LabelMonitoringServer = New-Object system.Windows.Forms.Label
-$LabelMonitoringServer.text = "Server"
-$LabelMonitoringServer.AutoSize = $false
-$LabelMonitoringServer.width = 60
-$LabelMonitoringServer.height = 20
-$LabelMonitoringServer.location = New-Object System.Drawing.Point(2, 15)
-$LabelMonitoringServer.Font = 'Microsoft Sans Serif,10'
-$MonitoringSettingsControls += $LabelMonitoringServer
-
-$TBMonitoringServer = New-Object system.Windows.Forms.TextBox
-$TBMonitoringServer.Tag = "MonitoringServer"
-$TBMonitoringServer.MultiLine = $False
-$TBMonitoringServer.text = $Config.MonitoringServer
-$TBMonitoringServer.AutoSize = $false
-$TBMonitoringServer.width = 260
-$TBMonitoringServer.height = 20
-$TBMonitoringServer.location = New-Object System.Drawing.Point(62, 15)
-$TBMonitoringServer.Font = 'Microsoft Sans Serif,10'
-$MonitoringSettingsControls += $TBMonitoringServer
-
-$CheckBoxReportToServer = New-Object system.Windows.Forms.CheckBox
-$CheckBoxReportToServer.Tag = "ReportToServer"
-$CheckBoxReportToServer.text = "Report to server"
-$CheckBoxReportToServer.AutoSize = $false
-$CheckBoxReportToServer.width = 130
-$CheckBoxReportToServer.height = 20
-$CheckBoxReportToServer.location = New-Object System.Drawing.Point(324, 15)
-$CheckBoxReportToServer.Font = 'Microsoft Sans Serif,10'
-$CheckBoxReportToServer.Checked = $Config.ReportToServer
-$MonitoringSettingsControls += $CheckBoxReportToServer
-
-$CheckBoxShowWorkerStatus = New-Object system.Windows.Forms.CheckBox
-$CheckBoxShowWorkerStatus.Tag = "ShowWorkerStatus"
-$CheckBoxShowWorkerStatus.text = "Show other workers"
-$CheckBoxShowWorkerStatus.AutoSize = $false
-$CheckBoxShowWorkerStatus.width = 145
-$CheckBoxShowWorkerStatus.height = 20
-$CheckBoxShowWorkerStatus.location = New-Object System.Drawing.Point(456, 15)
-$CheckBoxShowWorkerStatus.Font = 'Microsoft Sans Serif,10'
-$CheckBoxShowWorkerStatus.Checked = $Config.ShowWorkerStatus
-$MonitoringSettingsControls += $CheckBoxShowWorkerStatus
-
-$LabelMonitoringUser = New-Object system.Windows.Forms.Label
-$LabelMonitoringUser.text = "User ID"
-$LabelMonitoringUser.AutoSize = $false
-$LabelMonitoringUser.width = 60
-$LabelMonitoringUser.height = 20
-$LabelMonitoringUser.location = New-Object System.Drawing.Point(2, 37)
-$LabelMonitoringUser.Font = 'Microsoft Sans Serif,10'
-$MonitoringSettingsControls += $LabelMonitoringUser
-
-$TBMonitoringUser = New-Object system.Windows.Forms.TextBox
-$TBMonitoringUser.Tag = "MonitoringUser"
-$TBMonitoringUser.MultiLine = $False
-$TBMonitoringUser.text = $Config.MonitoringUser
-$TBMonitoringUser.AutoSize = $false
-$TBMonitoringUser.width = 260
-$TBMonitoringUser.height = 20
-$TBMonitoringUser.location = New-Object System.Drawing.Point(62, 37)
-$TBMonitoringUser.Font = 'Microsoft Sans Serif,10'
-$MonitoringSettingsControls += $TBMonitoringUser
-
-$ButtonGenerateMonitoringUser = New-Object system.Windows.Forms.Button
-$ButtonGenerateMonitoringUser.text = "Generate New User ID"
-$ButtonGenerateMonitoringUser.width = 160
-$ButtonGenerateMonitoringUser.height = 20
-$ButtonGenerateMonitoringUser.location = New-Object System.Drawing.Point(324, 37)
-$ButtonGenerateMonitoringUser.Font = 'Microsoft Sans Serif,10'
-$ButtonGenerateMonitoringUser.Enabled = ($TBMonitoringUser.text -eq "")
-$MonitoringSettingsControls += $ButtonGenerateMonitoringUser
-
-$ButtonGenerateMonitoringUser.Add_Click( {$TBMonitoringUser.text = [GUID]::NewGuid()})
-# Only enable the generate button when user is blank.
-$TBMonitoringUser.Add_TextChanged( { $ButtonGenerateMonitoringUser.Enabled = ($TBMonitoringUser.text -eq "") })
-
-
-$ButtonMonitoringWriteConfig = New-Object system.Windows.Forms.Button
-$ButtonMonitoringWriteConfig.text = "Save Config"
-$ButtonMonitoringWriteConfig.width = 100
-$ButtonMonitoringWriteConfig.height = 30
-$ButtonMonitoringWriteConfig.location = New-Object System.Drawing.Point(600, 15)
-$ButtonMonitoringWriteConfig.Font = 'Microsoft Sans Serif,10'
-$MonitoringSettingsControls += $ButtonMonitoringWriteConfig
-$ButtonMonitoringWriteConfig.Add_Click( {PrepareWriteConfig})
-
-
-
-# ***
-
-$MainForm | Add-Member -Name number -Value 0 -MemberType NoteProperty
-
-$TimerUI = New-Object System.Windows.Forms.Timer
-# $TimerUI.Add_Tick({TimerUI_Tick})
-
-$TimerUI.Stop()
-$ButtonPause.Add_Click( {
- If (!$Variables.Paused) {
- Update-Status("Stopping miners")
- $Variables.Paused = $True
-
- # Stop and start mining to immediately switch to paused state without waiting for current NPMCycle to finish
- $Variables.RestartCycle = $True
-
- $ButtonPause.Text = "Mine"
- Update-Status("Mining paused. BrainPlus and Earning tracker running.")
- }
- else {
- $Variables.Paused = $False
- $ButtonPause.Text = "Pause"
- $Variables | Add-Member -Force @{LastDonated = (Get-Date).AddDays(-1).AddHours(1)}
-
- # Stop and start mining to immediately switch to unpaused state without waiting for current sleep to finish
- $Variables.RestartCycle = $True
- }
- })
-
-$ButtonStart.Add_Click( {
- If ($Variables.Started) {
- $ButtonPause.Visible = $False
- Update-Status("Stopping cycle")
- $Variables.Started = $False
- Update-Status("Stopping jobs and miner")
-
- $Variables.EarningsTrackerJobs | % {$_ | Stop-Job -PassThru | Remove-Job}
- $Variables.EarningsTrackerJobs = @()
- $Variables.BrainJobs | % {$_ | Stop-Job -PassThru | Remove-Job}
- $Variables.BrainJobs = @()
-
- Stop-Mining
-
- # Stop idle tracking
- if ($IdleRunspace) {$IdleRunspace.Close()}
- if ($idlePowershell) {$idlePowershell.Dispose()}
-
- $LabelBTCD.Text = "$($Variables.CurrentProduct) $($Variables.CurrentVersion)"
- Update-Status("Idle")
- $ButtonStart.Text = "Start"
- # $TimerUI.Interval = 1000
- }
- else {
- if (!(IsLoaded(".\Core.ps1"))) {. .\Core.ps1; RegisterLoaded(".\Core.ps1")}
- if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
- PrepareWriteConfig
- $ButtonStart.Text = "Stop"
- InitApplication
- $Variables | add-Member -Force @{MainPath = (Split-Path $script:MyInvocation.MyCommand.Path)}
-
- Start-IdleTracking
-
- If ($Config.MineWhenIdle) {
- # Disable the pause button - pausing controlled by idle timer
- $Variables.Paused = $True
- $ButtonPause.Visible = $False
- }
- else {
- $ButtonPause.Visible = $True
- }
-
- Start-Mining
-
- $Variables.Started = $True
- }
- })
-
-$CheckBoxConsole.Add_Click( {
- If ($CheckBoxConsole.Checked) {
- $null = $ShowWindow::ShowWindowAsync($ConsoleHandle, 0)
- Update-Status("Console window hidden")
- }
- else {
- $null = $ShowWindow::ShowWindowAsync($ConsoleHandle, 8)
- Update-Status("Console window shown")
- }
- })
-
-$ShowWindow = Add-Type -MemberDefinition '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);' -Name Win32ShowWindowAsync -Namespace Win32Functions -PassThru
-$ParentPID = (Get-CimInstance -Class Win32_Process -Filter "ProcessID = $pid").ParentProcessId
-$ConsoleHandle = (Get-Process -Id $ParentPID).MainWindowHandle
-
-$MainForm.controls.AddRange($MainFormControls)
-$RunPage.controls.AddRange(@($RunPageControls))
-$SwitchingPage.controls.AddRange(@($SwitchingPageControls))
-$EstimationsPage.Controls.AddRange(@($EstimationsDGV))
-$ConfigPage.controls.AddRange($ConfigPageControls)
-$GroupMonitoringSettings.Controls.AddRange($MonitoringSettingsControls)
-$MonitoringPage.controls.AddRange($MonitoringPageControls)
-
-$MainForm.Add_Load( {Form_Load})
-# $TimerUI.Add_Tick({TimerUI_Tick})
-
-[void]$MainForm.ShowDialog()
-
-
+using module .\Includes\Include.psm1
+using module .\Includes\API.psm1
+
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: NemosMiner.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+[CmdletBinding()]
+param(
+ [Parameter(Mandatory = $false)]
+ [String[]]$Algorithm = @(), # i.e. @("Ethash", "Equihash", "Cryptonight") etc.
+ [Parameter(Mandatory = $false)]
+ [String]$APILogfile = "", # API will log all requests to this file, to disable leave empty
+ [Parameter(Mandatory = $false)]
+ [Int]$APIPort = 3999, # TCP Port for API & Web GUI
+ [Parameter(Mandatory = $false)]
+ [Boolean]$AutoUpdate = $false, # Autoupdate
+ [Parameter(Mandatory = $false)]
+ [Double]$BadShareRatioThreshold = 0.05, # Allowed ratio of bad shares (total / bad) as reported by the miner. If the ratio exceeds the configured threshold then the miner will get marked as failed. Allowed values: 0.00 - 1.00. Default of 0 disables this check
+ [Parameter(Mandatory = $false)]
+ [Boolean]$BalancesKeepAlive = $true, # If true will force mining at a pool to protect your earnings (some pools auto-purge the wallet after longer periods of inactivity, see '\Data\PoolData.Json' BalancesKeepAlive properties)
+ [Parameter(Mandatory = $false)]
+ [String[]]$BalancesTrackerIgnorePool, # Balances tracker will not track these pools
+ [Parameter(Mandatory = $false)]
+ [Switch]$BalancesTrackerLog = $false, # If true will store all balance tracker data in .\Logs\EarningTrackerLog.csv
+ [Parameter(Mandatory = $false)]
+ [UInt16]$BalancesTrackerPollInterval = 5, # minutes, Interval duration to trigger background task to collect pool balances & earnings dataset to 0 to disable
+ [Parameter(Mandatory = $false)]
+ [Switch]$CalculatePowerCost = $true, # If true power usage will be read from miners and calculate power cost, required for true profit calculation
+ [Parameter(Mandatory = $false)]
+ [String]$ConfigFile = ".\Config\Config.json", # Config file name
+ [Parameter(Mandatory = $false)]
+ [Int]$CPUMinerProcessPriority = "-2", # Process priority for CPU miners
+ [Parameter(Mandatory = $false)]
+ [String]$Currency = (Get-Culture).NumberFormat.CurrencySymbol, # Main 'real-money' currency, i.e. GBP, USD, AUD, NZD ect. Do not use crypto currencies
+ [Parameter(Mandatory = $false)]
+ [Int]$Delay = 0, # seconds between stop and start of miners, use only when getting blue screens on miner switches
+ [Parameter(Mandatory = $false)]
+ [Switch]$DisableDualAlgoMining = $false, # If true will not use any dual algorithm miners
+ [Parameter(Mandatory = $false)]
+ [Switch]$DisableMinerFee = $false, # Set to true to disable miner fees (Note: not all miners support turning off their built in fees, others will reduce the hashrate)
+ [Parameter(Mandatory = $false)]
+ [Switch]$DisableMinersWithFee = $false, # Set to true to disable all miners which contain fees
+ [Parameter(Mandatory = $false)]
+ [Switch]$DisableSingleAlgoMining = $false, # If true will not use any single algorithm miners
+ [Parameter(Mandatory = $false)]
+ [Int]$Donate = 13, # Minutes per Day
+ [Parameter(Mandatory = $false)]
+ [Double]$EarningsAdjustmentFactor = 1, # Default factor with which multiplies the prices reported by ALL pools. Allowed values: 0.0 - 1.0
+ [Parameter(Mandatory = $false)]
+ [Double]$EthashLowMemMinMemGB = 2GB, # Minimum EthashLowMem MinMem GB (sometimes Pool does not like GPUs with very little VRAM)
+ [Parameter(Mandatory = $false)]
+ [String[]]$ExcludeDeviceName = @(), # Array of disabled devices, e.g. @("CPU# 00", "GPU# 02"); by default all devices are enabled
+ [Parameter(Mandatory = $false)]
+ [String[]]$ExcludeMinerName = @(), # List of miners to be excluded; Either specify miner short name, e.g. "PhoenixMiner" (without '-v...') to exclude any version of the miner, or use the full miner name incl. version information
+ [Parameter(Mandatory = $false)]
+ [String[]]$ExtraCurrencies = @("ETC", "ETH", "mBTC"), # Extra currencies used in balances summary, Enter 'real-world' or crypto currencies, mBTC (milli BTC) is also allowed
+ [Parameter(Mandatory = $false)]
+ [Int]$GPUMinerProcessPriority = "-1", # Process priority for GPU miners
+ [Parameter(Mandatory = $false)]
+ [Double]$IdlePowerUsageW = 60, # Watt, Powerusage of idle system. Part of profit calculation.
+ [Parameter(Mandatory = $false)]
+ [Int]$IdleSec = 120, # seconds the system must be idle before mining starts (if MineWhenIdle -eq $true)
+ [Parameter(Mandatory = $false)]
+ [Switch]$IgnoreMinerFee = $false, # If true will ignore miner fee for earning & profit calculation
+ [Parameter(Mandatory = $false)]
+ [Switch]$IgnorePoolFee = $false, # If true will ignore pool fee for earning & profit calculation
+ [Parameter(Mandatory = $false)]
+ [Switch]$IgnorePowerCost = $false, # If true ill ignore power cost in best miner selection, instead miners with best earnings will be selected
+ [Parameter(Mandatory = $false)]
+ [Int]$Interval = 90, # Average cycle loop duration (seconds), min 60, max 3600
+ [Parameter(Mandatory = $false)]
+ [Switch]$LogBalanceAPIResponse = $false, # If true will log the pool balance API data
+ [Parameter(Mandatory = $false)]
+ [String[]]$LogToFile = @("Info", "Warn", "Error", "Verbose", "Debug"), # Log level detail to be written to log file, see Write-Message function
+ [Parameter(Mandatory = $false)]
+ [String[]]$LogToScreen = @("Info", "Warn", "Error", "Verbose", "Debug"), # Log level detail to be written to screen, see Write-Message function
+ [Parameter(Mandatory = $false)]
+ [ValidateRange(0, 1)]
+ [Double]$MinAccuracy = 0.5, # Use only pools with price accuracy greater than the configured value. Allowed values: 0.0 - 1.0 (0% - 100%)
+ [Parameter(Mandatory = $false)]
+ [Int]$MinDataSamples = 20, # Minimum number of hash rate samples required to store hash rate
+ [Parameter(Mandatory = $false)]
+ [Hashtable]$MinDataSamplesAlgoMultiplier = @{ "X16r" = 3 }, # Per algorithm multiply MinDataSamples by this value
+ [Parameter(Mandatory = $false)]
+ [Switch]$MinerInstancePerDeviceModel = $true, # If true will create separate miner instances per device model. This will increase profitability.
+ [Parameter(Mandatory = $false)]
+ [Int]$MinerSet = 1, # 0: Benchmark best miner per algorithm and device only; 1: Benchmark optimal miners (more than one per algorithm and device); 2: Benchmark all miners per algorithm and device;
+ [Parameter(Mandatory = $false)]
+ [Double]$MinerSwitchingThreshold = 10, # Will not switch miners unless another miner has n% higher earnings / profit
+ [Parameter(Mandatory = $false)]
+ [Switch]$MineWhenIdle = $false, # If true will start mining only if system is idle for $IdleSec seconds
+ [Parameter(Mandatory = $false)]
+ [String]$MinerWindowStyle = "minimized", # "minimized": miner window is minimized (default), but accessible; "normal": miner windows are shown normally; "hidden": miners will run as a hidden background task and are not accessible (not recommended)
+ [Parameter(Mandatory = $false)]
+ [Switch]$MinerWindowStyleNormalWhenBenchmarking = $true, # If true Miner window is shown normal when benchmarking (recommended to better see miner messages)
+ [Parameter(Mandatory = $false)]
+ [String]$MiningPoolHubAPIKey = "", # MiningPoolHub API Key (required to retrieve balance information)
+ [Parameter(Mandatory = $false)]
+ [String]$MiningPoolHubUserName = (Get-Random("MrPlus", "Nemo", "uselessguru")), # MiningPoolHub username
+ [Parameter(Mandatory = $false)]
+ [Int]$MinInterval = 1, # Minimum number of full cycles a miner must mine the same available algorithm@pool continously before switching is allowed (e.g. 3 would force a miner to stick mining algorithm@pool for min. 3 intervals before switching to another algorithm or pool)
+ [Parameter(Mandatory = $false)]
+ [Int]$MinWorker = 25, # Minimum workers mining the algorithm at the pool. If less miners are mining the algorithm then the pool will be disabled. This is also a per pool setting configurable in 'PoolsConfig.json'
+ [Parameter(Mandatory = $false)]
+ [String]$MonitoringServer = "https://nemosminer.com", # Monitoring server hostname, default "https://nemosminer.com"
+ [Parameter(Mandatory = $false)]
+ [String]$MonitoringUser = "", # Monitoring user ID as registered with monitoring server
+ [Parameter(Mandatory = $false)]
+ [String]$NiceHashAPIKey = "", # NiceHash API Key (required to retrieve balance information)
+ [Parameter(Mandatory = $false)]
+ [String]$NiceHashAPISecret = "", # NiceHash API Secret (required to retrieve balance information)
+ [Parameter(Mandatory = $false)]
+ [Switch]$NiceHashWalletIsInternal = $false, # Set to $true if NiceHashWallet is a NiceHash internal wallet (lower pool fees)
+ [Parameter(Mandatory = $false)]
+ [String]$NiceHashWallet = "", # NiceHash wallet, if left empty $Wallet is used
+ [Parameter(Mandatory = $false)]
+ [String]$NiceHashOrganizationId = "", # NiceHash Organization Id (required to retrieve balance information)
+ [Parameter(Mandatory = $false)]
+ [Switch]$OpenFirewallPorts = $true, # If true will open firewall ports for all miners (requires admin rights!)
+ [Parameter(Mandatory = $false)]
+ [String]$PayoutCurrency = "BTC", # i.e. BTC, LTC, ZEC, ETH etc., Default PayoutCurrency for all pools that have no other currency configured, PayoutCurrency is also a per pool setting (to be configured in PoolsConfig.json)
+ [Parameter(Mandatory = $false)]
+ [String]$PoolsConfigFile = ".\Config\PoolsConfig.json", # PoolsConfig file name
+ [Parameter(Mandatory = $false)]
+ [Uint16]$PoolBalancesUpdateInterval = 15, # Udate balances every n minutes to limit pool API requests. Allowed values 0 - 999 minutes. 0 will disable gathering pool balances
+ [Parameter(Mandatory = $false)]
+ [String[]]$PoolName = @("Blockmasters", "MiningPoolHub", "NiceHash", "ZergPoolCoins", "ZPool"),
+ [Parameter(Mandatory = $false)]
+ [Int]$PoolTimeout = 20, # Time (in seconds) until it aborts the pool request (useful if a pool's API is stuck). Note: do not set this value too small or NM will not be able to get any pool data
+ [Parameter(Mandatory = $false)]
+ [Hashtable]$PowerPricekWh = @{"00:00" = 0.26; "12:00" = 0.3 }, # Price of power per kW⋅h (in $Currency, e.g. CHF), valid from HH:mm (24hr format)
+ [Parameter(Mandatory = $false)]
+ [Hashtable]$PowerUsage = @{ }, # Static power usage per device in W, e.g. @{ "GPU#03" = 25, "GPU#04 = 55" } (in case HWiNFO cannot read power usage)
+ [Parameter(Mandatory = $false)]
+ [Double]$ProfitabilityThreshold = -99, # Minimum profit threshold, if profit is less than the configured value (in $Currency, e.g. CHF) mining will stop (except for benchmarking & power usage measuring)
+ [Parameter(Mandatory = $false)]
+ [String]$ProHashingAPIKey = "", # ProHashing API Key (required to retrieve balance information)
+ [Parameter(Mandatory = $false)]
+ [String]$ProHashingMiningMode = "PPS", # Either PPS (Pay Per Share) or PPLNS (Pay per Last N Shares)
+ [Parameter(Mandatory = $false)]
+ [String]$ProHashingUserName = "UselessGuru", # ProHashing UserName, if left empty then $UserName is used
+ [Parameter(Mandatory = $false)]
+ [String]$Proxy = "", # i.e http://192.0.0.1:8080
+ [Parameter(Mandatory = $false)]
+ [String]$Region = "Europe West", # Used to determine pool nearest to you.
+ [Parameter(Mandatory = $false)]
+ [Switch]$ReportToServer = $false, # I)f true will report worker status to central monitoring server
+ [Parameter(Mandatory = $false)]
+ [Switch]$ShowAccuracy = $true, # Show pool data accuracy column in miner overview
+ [Parameter(Mandatory = $false)]
+ [Switch]$ShowAllMiners = $false, # Always show all miners in miner overview (if $false, only the best miners will be shown except when in benchmark / powerusage measurement)
+ [Parameter(Mandatory = $false)]
+ [Switch]$ShowEarning = $true, # Show miner earning column in miner overview
+ [Parameter(Mandatory = $false)]
+ [Switch]$ShowCoinName = $true, # Show CoinName column in miner overview
+ [Parameter(Mandatory = $false)]
+ [Switch]$ShowCurrency = $true, # Show Currency column in miner overview
+ [Parameter(Mandatory = $false)]
+ [Switch]$ShowEarningBias = $true, # Show miner earning bias column in miner overview
+ [Parameter(Mandatory = $false)]
+ [Switch]$ShowMinerFee = $true, # Show miner fee column in miner overview (if fees are available, t.b.d. in miner files, Property '[Double]Fee')
+ [Parameter(Mandatory = $false)]
+ [Switch]$ShowPoolBalances = $false, # Display pool balances & earnings information in text window, requires BalancesTrackerPollInterval > 0
+ [Parameter(Mandatory = $false)]
+ [Switch]$ShowPoolFee = $true, # Show pool fee column in miner overview
+ [Parameter(Mandatory = $false)]
+ [Switch]$ShowPowerCost = $true, # Show Power cost column in miner overview (if power price is available, see PowerPricekWh)
+ [Parameter(Mandatory = $false)]
+ [Switch]$ShowProfit = $true, # Show miner profit column in miner overview (if power price is available, see PowerPricekWh)
+ [Parameter(Mandatory = $false)]
+ [Switch]$ShowProfitBias = $true, # Show miner profit bias column in miner overview (if power price is available, see PowerPricekWh)
+ [Parameter(Mandatory = $false)]
+ [Switch]$ShowPowerUsage = $true, # Show Power usage column in miner overview (if power price is available, see PowerPricekWh)
+ [Parameter(Mandatory = $false)]
+ [Switch]$ShowWorkerStatus = $true, # Show worker status from other rigs (data retrieved from monitoring server)
+ [Parameter(Mandatory = $false)]
+ [String]$SnakeTailExe = ".\Utils\SnakeTail.exe", # Path to optional external log reader (SnakeTail) [https://github.com/snakefoot/snaketail-net], leave empty to disable
+ [Parameter(Mandatory = $false)]
+ [String]$SnakeTailConfig = ".\Utils\NemosMiner_LogReader.xml", # Path to SnakeTail session config file
+ [Parameter(Mandatory = $false)]
+ [Switch]$StartGUIMinimized = $true,
+ [Parameter(Mandatory = $false)]
+ [String]$SSL = "prefer", # SSL pool connections: One of three values: 'Prefer' (use where available), 'Never' or 'Always' (pools that do not allow SSL are ignored)
+ [Parameter(Mandatory = $false)]
+ [String]$StartupMode = $false, # One of 'Idle', 'Paused' or 'Running'. This is the same as the buttons in the Web GUI
+ [Parameter(Mandatory = $false)]
+ [Boolean]$SubtractBadShares = $true, # If true will deduct rejected shares when calculating effective hashrates
+ [Parameter(Mandatory = $false)]
+ [Int]$SyncWindow = 3, # Cycles. Pool prices must all be all have been collected within the last 'SyncWindow' cycles, otherwise the biased value of older poll price data will get reduced more the older the data is
+ [Parameter(Mandatory = $false)]
+ [Switch]$Transcript = $false, # Enable to write PowerShell transcript files (for debugging)
+ [Parameter(Mandatory = $false)]
+ [Switch]$UsemBTC = $true, # If true will display BTC values in milli BTC
+ [Parameter(Mandatory = $false)]
+ [Switch]$UseMinerTweaks = $false, # If true will apply miner specific tweaks, e.g mild overclock. This may improve profitability at the expense of system stability (Admin rights are required)
+ [Parameter(Mandatory = $false)]
+ [String]$UIStyle = "Light", # Light or Full. Defines level of info displayed in main text window
+ [Parameter(Mandatory = $false)]
+ [Double]$UnrealPoolPriceFactor = 1.5, # Ignore pool if price is more than $Config.UnrealPoolPriceFactor higher than average price of all other pools with same algorithm & currency
+ [Parameter(Mandatory = $false)]
+ [Double]$UnrealMinerEarningFactor = 5, # Ignore miner if resulting profit is more than $Config.UnrealPoolPriceFactor higher than average price of all other miners with same algo
+ [Parameter(Mandatory = $false)]
+ [Switch]$UseAnycast = $true, # If true pools (currently ZergPool only) will use anycast for best network performance and ping times
+ [Parameter(Mandatory = $false)]
+ [Hashtable]$Wallets = @{ "BTC" = (Get-Random("134bw4oTorEJUUVFhokDQDfNqTs7rBMNYy", "1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE", "1GPSq8txFnyrYdXL8t6S94mYdF8cGqVQJF")); "ETC" = "0x7CF99ec9029A98AFd385f106A93977D8105Fec0f"; "ETH" = "0x92e6F22C1493289e6AD2768E1F502Fc5b414a287" },
+ [Parameter(Mandatory = $false)]
+ [Switch]$Watchdog = $true, # if true will automatically put pools and/or miners temporarily on hold it they fail $WatchdogCount times in a row
+ [Parameter(Mandatory = $false)]
+ [Int]$WatchdogCount = 3, # Number of watchdog timers
+ [Parameter(Mandatory = $false)]
+ [Switch]$WebGUI = $true, # If true launch Web GUI (recommended)
+ [Parameter(Mandatory = $false)]
+ [Switch]$WebGUIUseColor = $true, # If true Miners in the Web GUI will be shown with colored background depending on status
+ [Parameter(Mandatory = $false)]
+ [String]$WorkerName = "ID=$($env:computername)"
+)
+
+Set-Location (Split-Path $MyInvocation.MyCommand.Path)
+
+@"
+NemosMiner
+Copyright (c) 2018-$((Get-Date).Year) Nemo, MrPlus & UselessGuru
+This is free software, and you are welcome to redistribute it
+under certain conditions.
+https://github.com/Minerx117/NemosMiner/blob/master/LICENSE
+"@
+Write-Host "`nCopyright and license notices must be preserved.`n" -ForegroundColor Yellow
+
+# Initialize thread safe global variables
+New-Variable Config ([Hashtable]::Synchronized(@{ })) -Scope "Global" -Force -ErrorAction Stop
+New-Variable Stats ([Hashtable]::Synchronized(@{ })) -Scope "Global" -Force -ErrorAction Stop
+New-Variable Variables ([Hashtable]::Synchronized(@{ })) -Scope "Global" -Force -ErrorAction Stop
+
+# Load Branding
+$Variables.Branding = [PSCustomObject]@{
+ LogoPath = "https://raw.githubusercontent.com/Minerx117/UpDateData/master/NM.png"
+ BrandName = "NemosMiner"
+ BrandWebSite = "https://nemosminer.com"
+ ProductLabel = "NemosMiner"
+ Version = [System.Version]"4.0.0.28"
+}
+
+If ($PSVersiontable.PSVersion -lt [System.Version]"7.0.0") {
+ Write-Host "`nUnsupported PowerShell version $($PSVersiontable.PSVersion.ToString()) detected.`n$($Variables.Branding.BrandName) requires at least PowerShell version 7.0.0 which can be downloaded from https://github.com/PowerShell/powershell/releases.`n`n" -ForegroundColor Red
+ Start-Sleep -Seconds 30
+ Exit
+}
+
+# Create directories
+If (-not (Test-Path -Path ".\Cache" -PathType Container)) { New-Item -Path . -Name "Cache" -ItemType Directory -ErrorAction Ignore | Out-Null }
+If (-not (Test-Path -Path ".\Config" -PathType Container)) { New-Item -Path . -Name "Config" -ItemType Directory | Out-Null }
+If (-not (Test-Path -Path ".\Logs" -PathType Container)) { New-Item -Path . -Name "Logs" -ItemType Directory | Out-Null }
+
+# Expand paths
+$Variables.MainPath = (Split-Path $MyInvocation.MyCommand.Path)
+$Variables.LogFile = ".\Logs\$($Variables.Branding.ProductLabel)_$(Get-Date -Format "yyyy-MM-dd").log"
+$Variables.ConfigFile = "$($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($ConfigFile))".Replace("$(Convert-Path ".\")\", ".\")
+$Variables.PoolsConfigFile = "$($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($PoolsConfigFile))".Replace("$(Convert-Path ".\")\", ".\")
+$Variables.BalancesTrackerConfigFile = "$($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Config.BalancesTrackerConfigFile))".Replace("$(Convert-Path ".\")\", ".\")
+
+# Verify donation data
+$Variables.DonationData = Get-Content -Path ".\Data\DonationData.json" -ErrorAction Ignore | ConvertFrom-Json -ErrorAction Ignore -NoEnumerate
+If (-not $Variables.DonationData) {
+ Write-Message -Level Error "Terminating Error - Cannot continue! File '.\Data\DonationData.json' is not a valid JSON file. Please restore it from your original download."
+ Start-Sleep -Seconds 10
+ Exit
+}
+# Load algorithm list
+$Variables.Algorithms = Get-Content -Path ".\Data\Algorithms.json" -ErrorAction Ignore | ConvertFrom-Json -ErrorAction Ignore
+If (-not $Variables.Algorithms) {
+ Write-Message -Level Error "Terminating Error - Cannot continue! File '$($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath('.\Data\Algorithms.json'))' is not a valid JSON file. Please restore it from your original download."
+ Start-Sleep -Seconds 10
+ Exit
+}
+# Load coin names
+$Global:CoinNames = Get-Content -Path ".\Data\CoinNames.json" -ErrorAction Ignore | ConvertFrom-Json -ErrorAction Ignore
+If (-not $Global:CoinNames) {
+ Write-Message -Level Error "Terminating Error - Cannot continue! File '.\Data\CoinNames.json' is not a valid JSON file. Please restore it from your original download."
+ Start-Sleep -Seconds 10
+ Exit
+}
+# Load regions list
+$Variables.Regions = Get-Content -Path ".\Data\Regions.json" -ErrorAction Ignore | ConvertFrom-Json -ErrorAction Ignore
+If (-not $Variables.Regions) {
+ Write-Message -Level Error "Terminating Error - Cannot continue! File '.\Data\Regions.json' is not a valid JSON file. Please restore it from your original download."
+ Start-Sleep -Seconds 10
+ Exit
+}
+# Load pool data
+$Variables.PoolData = Get-Content -Path ".\Data\PoolData.json" -ErrorAction Ignore | ConvertFrom-Json -AsHashtable -ErrorAction Ignore | Get-SortedObject
+$Variables.PoolNames = @($Variables.PoolData.Keys)
+$Variables.PoolVariants = @(($Variables.PoolData.Keys | ForEach-Object { $Variables.PoolData.$_.Variant.Keys -replace " External$| Internal$" }) | Sort-Object -Unique)
+If (-not $Variables.PoolVariants) {
+ Write-Message -Level Error "Terminating Error - Cannot continue! File '.\Data\PoolData.json' is not a valid $($Variables.Branding.ProductLabel) JSON data file. Please restore it from your original download."
+ Start-Sleep -Seconds 10
+ Exit
+}
+# Load PoolsLastUsed data
+$Variables.PoolsLastUsed = (Get-Content -Path ".\Data\PoolsLastUsed.json" -ErrorAction Ignore | ConvertFrom-Json -AsHashtable -ErrorAction Ignore)
+If (-not $Variables.PoolsLastUsed.Keys) { $Variables.PoolsLastUsed = @{ } }
+
+# Load EarningsChart data to make it available early in Web GUI
+If (Test-Path -Path ".\Data\EarningsChartData.json" -PathType Leaf) { $Variables.EarningsChartData = Get-Content ".\Data\EarningsChartData.json" -ErrorAction Ignore | ConvertFrom-Json -ErrorAction Ignore }
+
+$Variables.AllCommandLineParameters = [Ordered]@{ }
+$MyInvocation.MyCommand.Parameters.Keys | Where-Object { Get-Variable $_ -ErrorAction Ignore } | Sort-Object | ForEach-Object {
+ $Variables.AllCommandLineParameters.$_ = Get-Variable $_ -ValueOnly -ErrorAction Ignore
+ If ($Variables.AllCommandLineParameters.$_ -is [Switch]) { $Variables.AllCommandLineParameters.$_ = [Boolean]$Variables.AllCommandLineParameters.$_ }
+ Remove-Variable $_ -ErrorAction Ignore
+}
+
+# Read configuration
+Read-Config -ConfigFile $Variables.ConfigFile
+
+# Start transcript log
+If ($Config.Transcript -eq $true) { Start-Transcript ".\Logs\$((Get-Item $MyInvocation.MyCommand.Path).BaseName)-Transcript_$(Get-Date -Format "yyyy-MM-dd_HH-mm-ss").log" }
+
+# Start Log reader (SnakeTail) [https://github.com/snakefoot/snaketail-net]
+Start-LogReader
+
+Write-Message -Level Info "Starting $($Variables.Branding.ProductLabel)® v$($Variables.Branding.Version) © 2017-$((Get-Date).Year) Nemo, MrPlus and UselessGuru"
+If (-not $Variables.FreshConfig) { Write-Message -Level Info "Using configuration file '$($Variables.ConfigFile)'." }
+Write-Host ""
+
+#Prerequisites check
+Write-Message -Level Verbose "Verifying pre-requisites..."
+$Prerequisites = @(
+ "$env:SystemRoot\System32\MSVCR120.dll",
+ "$env:SystemRoot\System32\VCRUNTIME140.dll",
+ "$env:SystemRoot\System32\VCRUNTIME140_1.dll"
+)
+
+If ($PrerequisitesMissing = @($Prerequisites | Where-Object { -not (Test-Path $_ -PathType Leaf) })) {
+ $PrerequisitesMissing | ForEach-Object { Write-Message -Level Warn "$_ is missing." }
+ Write-Message -Level Error "Please install the required runtime modules. Download and extract"
+ Write-Message -Level Error "https://github.com/Minerx117/Visual-C-Runtimes-All-in-One-Sep-2019/releases/download/sep2019/Visual-C-Runtimes-All-in-One-Sep-2019.zip"
+ Write-Message -Level Error "and run 'install_all.bat' (Admin rights are required)."
+ Start-Sleep -Seconds 10
+ Exit
+}
+
+If ([System.Environment]::OSVersion.Version -lt [Version]"10.0.0.0" -and -not (Get-Command Get-PnpDevice -ErrorAction Ignore)) {
+ Write-Message -Level Error "Windows Management Framework 5.1 is missing."
+ Write-Message -Level Error "Please install the required runtime modules from https://www.microsoft.com/en-us/download/details.aspx?id=54616"
+ Start-Sleep -Seconds 10
+ Exit
+}
+
+Write-Message -Level Verbose "Pre-requisites verification OK."
+Remove-Variable Prerequisites, PrerequisitesMissing
+
+# Check if new version is available
+Get-NMVersion
+
+Write-Host "Importing modules..." -ForegroundColor Yellow
+Try {
+ Add-Type -Path ".\Cache\~OpenCL_$($PSVersionTable.PSVersion.ToString()).dll" -ErrorAction Stop
+}
+Catch {
+ Remove-Item ".\Cache\~OpenCL_$($PSVersionTable.PSVersion.ToString()).dll" -Force -ErrorAction Ignore
+ Add-Type -Path ".\Includes\OpenCL\*.cs" -OutputAssembly ".\Cache\~OpenCL_$($PSVersionTable.PSVersion.ToString()).dll"
+ Add-Type -Path ".\Cache\~OpenCL_$($PSVersionTable.PSVersion.ToString()).dll"
+}
+
+Try {
+ Add-Type -Path ".\Cache\~CPUID_$($PSVersionTable.PSVersion.ToString()).dll" -ErrorAction Stop
+}
+Catch {
+ Remove-Item ".\Cache\~CPUID_$($PSVersionTable.PSVersion.ToString()).dll" -Force -ErrorAction Ignore
+ Add-Type -Path ".\Includes\CPUID.cs" -OutputAssembly ".\Cache\~CPUID_$($PSVersionTable.PSVersion.ToString()).dll"
+ Add-Type -Path ".\Cache\~CPUID_$($PSVersionTable.PSVersion.ToString()).dll"
+}
+Add-Type -AssemblyName System.Windows.Forms
+[System.Windows.Forms.Application]::EnableVisualStyles()
+[Void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisualization")
+Import-Module NetSecurity -ErrorAction SilentlyContinue
+Import-Module Defender -ErrorAction SilentlyContinue -SkipEditionCheck
+
+# Unblock files
+If (Get-Item .\* -Stream Zone.*) {
+ Write-Host "Unblocking files that were downloaded from the internet..." -ForegroundColor Yellow
+ If (Get-Command "Unblock-File" -ErrorAction SilentlyContinue) { Get-ChildItem -Path . -Recurse | Unblock-File }
+ If ((Get-Command "Get-MpPreference" -ErrorAction Ignore) -and (Get-MpComputerStatus -ErrorAction Ignore) -and (Get-MpPreference).ExclusionPath -notcontains (Convert-Path .)) {
+ Start-Process "pwsh" "-Command Import-Module Defender; Add-MpPreference -ExclusionPath '$(Convert-Path .)'" -Verb runAs
+ }
+}
+
+# Update config file to include all new config items
+If ($Variables.AllCommandLineParameters -and (-not $Config.ConfigFileVersion -or [System.Version]::Parse($Config.ConfigFileVersion) -lt $Variables.Branding.Version)) {
+ Update-ConfigFile -ConfigFile $Variables.ConfigFile
+}
+
+If (Test-Path -Path .\Cache\VertHash.dat -PathType Leaf) {
+ Write-Message -Level Verbose "Verifying integrity of VertHash data file '.\Cache\VertHash.dat'..."
+ $VertHashDatCheckJob = Start-ThreadJob -ThrottleLimit 99 -ScriptBlock { (Get-FileHash ".\Cache\VertHash.dat").Hash -eq "A55531E843CD56B010114AAF6325B0D529ECF88F8AD47639B6EDEDAFD721AA48" }
+}
+
+$Variables.Summary = "Loading miner device information..."
+Write-Message -Level Verbose $Variables.Summary
+
+$Variables.SupportedCPUDeviceVendors = @("AMD", "INTEL")
+$Variables.SupportedGPUDeviceVendors = @("AMD", "NVIDIA")
+
+$Variables.Devices = [Device[]](Get-Device -Refresh)
+$Variables.Devices | Where-Object { $_.Type -eq "CPU" -and $_.Vendor -notin $Variables.SupportedCPUDeviceVendors } | ForEach-Object { $_.State = [DeviceState]::Unsupported; $_.Status = "Disabled (Unsupported Vendor: '$($_.Vendor)')" }
+$Variables.Devices | Where-Object { $_.Type -eq "GPU" -and $_.Vendor -notin $Variables.SupportedGPUDeviceVendors } | ForEach-Object { $_.State = [DeviceState]::Unsupported; $_.Status = "Disabled (Unsupported Vendor: '$($_.Vendor)')" }
+
+$Variables.Devices | Where-Object Name -In $Config.ExcludeDeviceName | Where-Object { $_.State -NE [DeviceState]::Unsupported } | ForEach-Object { $_.State = [DeviceState]::Disabled; $_.Status = "Disabled (ExcludeDeviceName: '$($_.Name)')" }
+
+Write-Host "Setting variables..." -ForegroundColor Yellow
+$Variables.AvailableCommandLineParameters = @($AllCommandLineParameters.Keys | Sort-Object)
+
+# Build driver version table
+$Variables.DriverVersion = [PSCustomObject]@{ }
+$Variables.DriverVersion | Add-Member "CIM" ([PSCustomObject]@{ })
+$Variables.DriverVersion.CIM | Add-Member "CPU" ((($Variables.Devices | Where-Object Type -EQ "CPU").CIM.DriverVersion | Select-Object -First 1) -split ' ' | Select-Object -First 1)
+$Variables.DriverVersion.CIM | Add-Member "AMD" ((($Variables.Devices | Where-Object { $_.Type -eq "GPU" -and $_.Vendor -eq "AMD" }).CIM.DriverVersion | Select-Object -First 1) -split ' ' | Select-Object -First 1)
+$Variables.DriverVersion.CIM | Add-Member "NVIDIA" ((($Variables.Devices | Where-Object { $_.Type -eq "GPU" -and $_.Vendor -eq "NVIDIA" }).CIM.DriverVersion | Select-Object -First 1) -split ' ' | Select-Object -First 1)
+$Variables.DriverVersion | Add-Member "OpenCL" ([PSCustomObject]@{ })
+$Variables.DriverVersion.OpenCL | Add-Member "CPU" ((($Variables.Devices | Where-Object Type -EQ "CPU").OpenCL.DriverVersion | Select-Object -First 1) -split ' ' | Select-Object -First 1)
+$Variables.DriverVersion.OpenCL | Add-Member "AMD" ((($Variables.Devices | Where-Object { $_.Type -eq "GPU" -and $_.Vendor -eq "AMD" }).OpenCL.DriverVersion | Select-Object -First 1) -split ' ' | Select-Object -First 1)
+$Variables.DriverVersion.OpenCL | Add-Member "NVIDIA" ((($Variables.Devices | Where-Object { $_.Type -eq "GPU" -and $_.Vendor -eq "NVIDIA" }).OpenCL.DriverVersion | Select-Object -First 1) -split ' ' | Select-Object -First 1)
+$Variables.DriverVersion | Add-Member "CUDA" $(Switch ([System.Version]$Variables.DriverVersion.OpenCL.NVIDIA) { { $_ -ge [System.Version]"510.39.01" } { "11.6"; Break }; { $_ -ge [System.Version]"495.29.05" } { "11.5"; Break }; { $_ -ge [System.Version]"470.57.02" } { "11.4"; Break }; { $_ -ge [System.Version]"465.19.01" } { "11.3"; Break }; { $_ -ge [System.Version]"460.27.04" } { "11.2"; Break }; { $_ -ge [System.Version]"455.23.05" } { "11.1"; Break }; { $_ -ge [System.Version]"450.36.06" } { "11.0"; Break };{ $_ -ge [System.Version]"418.40.04" } { "10.1"; Break }; { $_ -ge [System.Version]"410.48.00" } { "10.0"; Break }; { $_ -ge [System.Version]"396.00" } { "9.2"; Break }; { $_ -ge [System.Version]"390.00" } { "9.1"; Break }; { $_ -ge [System.Version]"384.00" } { "9.0"; Break }; Default { $null } })
+$Variables.Devices | Where-Object { $_.Type -EQ "GPU" -and $_.Vendor -eq "NVIDIA" } | ForEach-Object { $_ | Add-Member CUDAVersion $Variables.DriverVersion.CUDA }
+
+# Driver version have changed
+If ((Get-Content -Path ".\Data\DriverVersion.json" -ErrorAction Ignore | ConvertFrom-Json | ConvertTo-Json -compress) -ne ($Variables.DriverVersion | ConvertTo-Json -compress)) {
+ If (Test-Path -Path ".\Data\DriverVersion.json" -PathType Leaf) { Write-Message -Level Warn "Graphis card driver version data changed. It is recommended to re-download all binaries." }
+ $Variables.DriverVersion | ConvertTo-Json | Out-File -FilePath ".\Data\DriverVersion.json" -Encoding utf8NoBOM -ErrorAction Ignore -Force
+}
+
+$Variables.BrainJobs = @{ }
+$Variables.IsLocalAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")
+$Variables.Miners = [Miner[]]@()
+$Variables.NewMiningStatus = If ($Config.StartupMode -match "Paused|Running") { $Config.StartupMode } Else { "Idle" }
+$Variables.MyIP = (Get-NetIPConfiguration | Where-Object IPv4DefaultGateway).IPv4Address.IPAddress
+$Variables.Pools = [Pool[]]@()
+$Variables.RestartCycle = $true # To simulate first loop
+$Variables.ScriptStartTime = (Get-Process -id $PID).StartTime.ToUniversalTime()
+$Variables.WatchdogTimers = @()
+
+# Set operational values for text window
+$Variables.ShowAccuracy = $Config.ShowAccuracy
+$Variables.ShowAllMiners = $Config.ShowAllMiners
+$Variables.ShowEarning = $Config.ShowEarning
+$Variables.ShowEarningBias = $Config.ShowEarningBias
+$Variables.ShowMinerFee = $Config.ShowMinerFee
+$Variables.ShowPoolBalances = $Config.ShowPoolBalances
+$Variables.ShowPoolFee = $Config.ShowPoolFee
+$Variables.ShowPowerCost = $Config.ShowPowerCost
+$Variables.ShowPowerUsage = $Config.ShowPowerUsage
+$Variables.ShowProfit = $Config.ShowProfit
+$Variables.ShowProfitBias = $Config.ShowProfitBias
+$Variables.ShowCoinName = $Config.ShowCoinName
+$Variables.ShowCurrency = $Config.ShowCurrency
+$Variables.UIStyle = $Config.UIStyle
+
+# Align CUDA id with nvidia-smi order
+$env:CUDA_DEVICE_ORDER = 'PCI_BUS_ID'
+# For AMD
+$env:GPU_FORCE_64BIT_PTR = 1
+$env:GPU_MAX_HEAP_SIZE = 100
+$env:GPU_USE_SYNC_OBJECTS = 1
+$env:GPU_MAX_ALLOC_PERCENT = 100
+$env:GPU_SINGLE_ALLOC_PERCENT = 100
+$env:GPU_MAX_WORKGROUP_SIZE = 256
+
+# Rename existing switching log
+If (Test-Path -Path ".\Logs\SwitchingLog.csv" -PathType Leaf) { Get-ChildItem -Path ".\Logs\SwitchingLog.csv" -File | Rename-Item -NewName { "SwitchingLog$($_.LastWriteTime.toString('_yyyy-MM-dd_HH-mm-ss')).csv" } }
+
+If (Test-Path -Path .\Cache\VertHash.dat -PathType Leaf) {
+ If ($VertHashDatCheckJob | Wait-Job -Timeout 60 | Receive-Job -Wait -AutoRemoveJob) {
+ Write-Message -Level Verbose "VertHash data file integrity check: OK."
+ }
+ Else {
+ Remove-Item -Path ".\Cache\VertHash.dat" -Force -ErrorAction Ignore
+ Write-Message -Level Warn "VertHash data file '.\Cache\VertHash.dat' is corrupt -> file deleted. It will be recreated by the miners if needed."
+ }
+ Remove-Variable VertHashDatCheckJob -ErrorAction Ignore
+}
+
+If ($Config.WebGUI -eq $true) {
+ Initialize-API
+ Start-LogReader # To bring SnakeTail back in focus
+}
+
+If ($Variables.APIVersion -ne "" -and $Variables.FreshConfig -eq $true) {
+ $Variables.Summary = "Change your settings and apply the configuration; then click 'Start mining'."
+ $wshell = New-Object -ComObject Wscript.Shell
+ $wshell.Popup("This is the first time you have started $($Variables.Branding.ProductLabel).`n`nUse the configuration editor to change your settings and apply the configuration.`n`n`Start making money by clicking 'Start mining'.`n`nHappy Mining!", 0, "Welcome to $($Variables.Branding.ProductLabel) v$($Variables.Branding.Version)", 4096) | Out-Null
+ Remove-Variable wshell
+}
+
+Function Get-Chart {
+
+ Function Get-NextColor {
+ Param(
+ [Parameter(Mandatory = $true)]
+ [Byte[]]$Colors,
+ [Parameter(Mandatory = $true)]
+ [Int[]]$Factors
+ )
+
+ # Apply change Factor
+ 0..($Colors.Count - 1) | ForEach-Object {
+ $Colors[$_] = [math]::Abs(($Colors[$_] + $Factors[$_]) % 256)
+ }
+ $Colors
+ }
+
+ If (Test-Path -Path ".\Data\DailyEarnings.csv" -PathType Leaf) {
+
+ $DatasourceRaw = Import-Csv ".\Data\DailyEarnings.csv" -ErrorAction Ignore
+ $DatasourceRaw | ForEach-Object { $_.Date = [DateTime]::parseexact($_.Date, "yyyy-MM-dd", $null) }
+
+ $Datasource = $DatasourceRaw | Where-Object Date -le (Get-Date).AddDays(-1)
+ $Datasource = $Datasource | Where-Object Date -in @($Datasource.Date | Sort-Object -Unique | Select-Object -Last 14)
+ $Datasource | ForEach-Object { $_.DailyEarnings = [Double]($_.DailyEarnings) * $Variables.Rates.($_.Currency).($Config.Currency) }
+ $Datasource = $Datasource | Select-Object *, @{ Name = "DaySum"; Expression = { $Date = $_.Date; ((($Datasource | Where-Object { $_.Date -eq $Date }).DailyEarnings) | Measure-Object -Sum).Sum } }
+
+ $ChartTitle = New-Object System.Windows.Forms.DataVisualization.Charting.Title
+ $ChartTitle.Text = "Earnings Tracker: Earnings of the past 14 active days"
+ $ChartTitle.Font = [System.Drawing.Font]::new("Arial", 10)
+ $ChartTitle.Alignment = "TopCenter"
+ $EarningsChart1.Titles.Clear()
+ $EarningsChart1.Titles.Add($ChartTitle)
+
+ $ChartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
+ $ChartArea.BackColor = [System.Drawing.Color]::FromArgb(255, 32, 50, 50) #"#2B3232"
+ $ChartArea.BackSecondaryColor = [System.Drawing.Color]::FromArgb(255, 119, 126, 126) #"#777E7E"
+ $ChartArea.BackGradientStyle = 3
+ $ChartArea.AxisX.LabelStyle.Enabled = $false
+ $ChartArea.AxisX.Enabled = 2
+ $ChartArea.AxisX.MajorGrid.Enabled = $false
+ $ChartArea.AxisY.MajorGrid.Enabled = $true
+ $ChartArea.AxisY.MajorGrid.LineColor = [System.Drawing.Color]::FromArgb(255, 255, 255, 255) #"#FFFFFF"
+ $ChartArea.AxisY.LabelAutoFitStyle = $ChartArea.AxisY.labelAutoFitStyle - 4
+ $ChartArea.AxisY.Interval = [Math]::Ceiling(($Datasource.DaySum | Measure-Object -Maximum).Maximum / 4)
+ $EarningsChart1.ChartAreas.Clear()
+ $EarningsChart1.ChartAreas.Add($ChartArea)
+
+ $EarningsChart1.Series.Clear()
+ [Void]$EarningsChart1.Series.Add("TotalEarning")
+ $EarningsChart1.Series["TotalEarning"].ChartType = "Column"
+ $EarningsChart1.Series["TotalEarning"].BorderWidth = 3
+ $EarningsChart1.Series["TotalEarning"].ChartArea = "ChartArea1"
+ $EarningsChart1.Series["TotalEarning"].Color = [System.Drawing.Color]::FromArgb(255, 255, 255, 255) #"FFFFFF"
+ $EarningsChart1.Series["TotalEarning"].label = "#VALY{N3}"
+ $EarningsChart1.Series["TotalEarning"].ToolTip = "#VALX: #VALY $($Config.Currency)"
+ $Datasource | Select-Object Date, DaySum -Unique | ForEach-Object { $EarningsChart1.Series["TotalEarning"].Points.addxy( $_.Date.ToShortDateString(), ("{0:N5}" -f $_.DaySum)) | Out-Null }
+
+ $EarningsChart1.BringToFront()
+
+ $Datasource = $DatasourceRaw | Where-Object Date -eq (Get-Date).Date | Where-Object DailyEarnings -gt 0 | Sort-Object DailyEarnings -Descending
+ $Datasource | ForEach-Object { $_.DailyEarnings = [Double]$_.DailyEarnings * $Variables.Rates.($_.Currency).($Config.Currency) }
+
+ $ChartTitle = New-Object System.Windows.Forms.DataVisualization.Charting.Title
+ $ChartTitle.Text = "Todays earnings per pool"
+ $ChartTitle.Font = [System.Drawing.Font]::new("Arial", 10)
+ $ChartTitle.Alignment = "TopCenter"
+ $EarningsChart2.Titles.Clear()
+ $EarningsChart2.Titles.Add($ChartTitle)
+
+ $ChartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
+ $ChartArea.BackColor = [System.Drawing.Color]::FromArgb(255, 32, 50, 50) #"#2B3232"
+ $ChartArea.BackSecondaryColor = [System.Drawing.Color]::FromArgb(255, 119, 126, 126) #"#777E7E"
+ $ChartArea.BackGradientStyle = 3
+ $ChartArea.AxisX.LabelStyle.Enabled = $false
+ $ChartArea.AxisX.Enabled = 2
+ $ChartArea.AxisX.MajorGrid.Enabled = $false
+ $ChartArea.AxisY.MajorGrid.Enabled = $true
+ $ChartArea.AxisY.MajorGrid.LineColor = [System.Drawing.Color]::FromArgb(255, 255, 255, 255) #"#FFFFFF"
+ $ChartArea.AxisY.LabelAutoFitStyle = $ChartArea.AxisY.labelAutoFitStyle - 4
+ $ChartArea.AxisY.Interval = [Math]::Ceiling(($Datasource.DailyEarnings | Measure-Object -Sum).Sum / 4)
+ $EarningsChart2.ChartAreas.Clear()
+ $EarningsChart2.ChartAreas.Add($ChartArea)
+
+ $EarningsChart2.Series.Clear()
+ $Colors = @(255, 255, 255, 255) #"FFFFFF"
+ ForEach ($Pool in $Datasource.Pool) {
+ $Colors = (Get-NextColor -Colors $Colors -Factors -0, -20, -20, -20)
+
+ [Void]$EarningsChart2.Series.Add($Pool)
+ $EarningsChart2.Series[$Pool].ChartType = "StackedColumn"
+ $EarningsChart2.Series[$Pool].BorderWidth = 1
+ $EarningsChart2.Series[$Pool].BorderColor = [System.Drawing.Color]::FromArgb(255, 119, 126 ,126) #"#FFFFFF"
+ $EarningsChart2.Series[$Pool].ChartArea = "ChartArea1"
+ $EarningsChart2.Series[$Pool].Color = [System.Drawing.Color]::FromArgb($Colors[0], $Colors[1], $Colors[2], $Colors[3])
+ $EarningsChart2.Series[$Pool].ToolTip = "#SERIESNAME: #VALY $($Config.Currency)"
+ $Datasource | Where-Object Pool -eq $Pool | ForEach-Object { $EarningsChart2.Series[$Pool].Points.addxy($_.Pool, ("{0:N3}" -f $_.DailyEarnings)) | Out-Null }
+ }
+ $EarningsChart2.BringToFront()
+ }
+}
+
+Function Update-TabControl {
+
+ $Mainform.Cursor = [System.Windows.Forms.Cursors]::WaitCursor
+
+ Switch ($TabControl.SelectedTab.Text) {
+ "Run" {
+ If ($Variables.Miners) {
+ $RunningMinersDGV.DataSource = $Variables.Miners | Where-Object { $_.Status -eq "Running" } | Select-Object @(
+ @{ Name = "Device(s)"; Expression = { $_.DeviceName -join "; " } },
+ @{ Name = "Miner"; Expression = { "$($_.Name) $($_.Info)" } },
+ @{ Name = "Account"; Expression = { ($_.Workers.Pool.User | Select-Object -Unique | ForEach-Object { $_ -split '\.' | Select-Object -First 1 } | Select-Object -Unique) -join ' & ' } },
+ @{ Name = "Earning $($Config.Currency)/day"; Expression = { If (-not [Double]::IsNaN($_.Earning)) { ($_.Earning * $Variables.Rates.BTC.($Config.Currency)).ToString("N3") } Else { "Unknown" } } },
+ @{ Name = "Profit $($Config.Currency)/day"; Expression = { If ($Variables.CalculatePowerCost -and -not [Double]::IsNaN($_.Profit)) { ($_.Profit * $Variables.Rates.BTC.($Config.Currency)).ToString("N3") } Else { "Unknown" } } },
+ @{ Name = "Pool"; Expression = { ($_.WorkersRunning.Pool | ForEach-Object { (@(@($_.Name | Select-Object) + @($_.Coin | Select-Object))) -join '-' }) -join ' & ' } },
+ @{ Name = "Hashrate"; Expression = { If ($_.Speed_Live -contains $null) { ($_.Speed_Live | ForEach-Object { "$($_ | ConvertTo-Hash)/s" -replace "\s+", " " }) -join ' & ' } Else { ($_.Workers.Speed | ForEach-Object { "$($_ | ConvertTo-Hash)/s" -replace "\s+", " " }) -join ' & ' } } },
+ @{ Name = "Active (hhh:mm:ss)"; Expression = { "{0}:{1:mm}:{1:ss}" -f [math]::floor(((Get-Date).ToUniversalTime() - $_.BeginTime).TotalDays * 24), ((Get-Date).ToUniversalTime() - $_.BeginTime) } },
+ @{ Name = "Total Active (hhh:mm:ss)"; Expression = { "{0}:{1:mm}:{1:ss}" -f [math]::floor($_.TotalMiningDuration.TotalDays * 24), $_.TotalMiningDuration } }
+ ) | Sort-Object "Device(s)" | Out-DataTable
+
+ $RunningMinersDGV.ClearSelection()
+
+ If ($RunningMinersDGV.Columns) {
+ $RunningMinersDGV.Columns[0].FillWeight = 75
+ $RunningMinersDGV.Columns[1].FillWeight = 225
+ $RunningMinersDGV.Columns[2].FillWeight = 150
+ $RunningMinersDGV.Columns[3].FillWeight = 50
+ $RunningMinersDGV.Columns[4].FillWeight = 50
+ $RunningMinersDGV.Columns[5].FillWeight = 100
+ $RunningMinersDGV.Columns[6].FillWeight = 75
+ $RunningMinersDGV.Columns[7].FillWeight = 65
+ $RunningMinersDGV.Columns[8].FillWeight = 65
+ }
+ $LabelRunningMiners.Text = "Running Miners - Updated $((Get-Date).ToString())"
+ }
+ Else { $LabelRunningMiners.Text = "Waiting for data..." }
+ }
+ "Earnings" {
+
+ Get-Chart
+
+ If ($Variables.Balances) {
+ $EarningsDGV.DataSource = $Variables.Balances.Values | Select-Object @(
+ @{ Name = "Pool"; Expression = { "$($_.Pool) [$($_.Currency)]" } },
+ @{ Name = "Balance ($($Config.Currency))"; Expression = { "{0:N8}" -f ($_.Balance * $Variables.Rates.($_.Currency).($Config.Currency)) } },
+ @{ Name = "Avg. $($Config.Currency)/day"; Expression = { "{0:N8}" -f ($_.AvgDailyGrowth * $Variables.Rates.($_.Currency).($Config.Currency)) } },
+ @{ Name = "$($Config.Currency) in 1h"; Expression = { "{0:N6}" -f ($_.Growth1 * $Variables.Rates.($_.Currency).($Config.Currency)) } },
+ @{ Name = "$($Config.Currency) in 6h"; Expression = { "{0:N6}" -f ($_.Growth6 * $Variables.Rates.($_.Currency).($Config.Currency)) } },
+ @{ Name = "$($Config.Currency) in 24h"; Expression = { "{0:N6}" -f ($_.Growth24 * $Variables.Rates.($_.Currency).($Config.Currency)) } },
+ @{ Name = "Projected paydate"; Expression = { If ($_.ProjectedPayDate -is [DateTime]) { $_.ProjectedPayDate.ToShortDateString() } Else { $_.ProjectedPayDate } } },
+ @{ Name = "PayoutThreshold"; Expression = { "$($_.PayoutThreshold) $($_.PayoutThresholdCurrency) ($('{0:P1}' -f $($_.Balance / $_.PayoutThreshold * $Variables.Rates.($_.PayoutThresholdCurrency).($_.Currency))))" } }
+ ) | Sort-Object Pool | Out-DataTable
+
+ $EarningsDGV.ClearSelection()
+
+ If ($EarningsDGV.Columns) {
+ $EarningsDGV.Columns[0].FillWeight = 140
+ $EarningsDGV.Columns[1].FillWeight = 90
+ $EarningsDGV.Columns[2].FillWeight = 90
+ $EarningsDGV.Columns[3].FillWeight = 75
+ $EarningsDGV.Columns[4].FillWeight = 75
+ $EarningsDGV.Columns[5].FillWeight = 75
+ $EarningsDGV.Columns[6].FillWeight = 80
+ $EarningsDGV.Columns[7].FillWeight = 100
+ }
+ $LabelEarnings.Text = "Earnings statistics per pool - Updated $((Get-ChildItem -Path ".\Data\DailyEarnings.csv" -ErrorAction Ignore).LastWriteTime.ToString())"
+ }
+ Else { $LabelEarnings.Text = "Waiting for data..." }
+ }
+ "Switching Log" {
+ CheckBoxSwitching_Click
+ }
+ "Rig Monitoring" {
+
+ Receive-MonitoringData
+
+ If ([Boolean]$Variables.APIRunspace) {
+ $ConfigMonitoring.Text = "To edit the monitoring settings use the Web GUI"
+ $ConfigMonitoring.Enabled = $true
+ }
+ Else {
+ $ConfigMonitoring.Text = "The monitoring settings must be configured by editing '$($Variables.ConfigFile)'."
+ $ConfigMonitoring.Enabled = $false
+ }
+
+ If ($Variables.Workers) {
+ $Variables.Workers | ForEach-Object {
+ $TimeSinceLastReport = New-TimeSpan -Start $_.date -End (Get-Date)
+ # Show friendly time since last report in seconds, minutes, hours and days
+ $TimeSinceLastReportText = ""
+ If ($TimeSinceLastReport.Days -ge 1) { $TimeSinceLastReportText += " {0:N0} day$(If ($TimeSinceLastReport.Days -ne 1) { "s" })" -f $TimeSinceLastReport.Days }
+ If ($TimeSinceLastReport.Hours -ge 1) { $TimeSinceLastReportText += " {0:N0} hour$(If ($TimeSinceLastReport.Hours -ne 1) { "s" })" -f $TimeSinceLastReport.Hours }
+ If ($TimeSinceLastReport.Minutes -ge 1) { $TimeSinceLastReportText += " {0:N0} minute$(If ($TimeSinceLastReport.Minutes -ne 1) { "s" })" -f $TimeSinceLastReport.Minutes }
+ If ($TimeSinceLastReport.Seconds -ge 1) { $T4imeSinceLastReportText += " {0:N0} second$(If ($TimeSinceLastReport.Seconds -ne 1) { "s" })" -f $TimeSinceLastReport.Seconds }
+ If ($TimeSinceLastReportText) { $_ | Add-Member -Force @{ TimeSinceLastReportText = "$($TimeSinceLastReportText.trim()) ago" } }
+ Else { $_ | Add-Member -Force @{ TimeSinceLastReportText = "just now" } }
+ }
+
+ $nl = "`n" # Must use variable, cannot join with '`n' directly
+ $WorkersDGV.DataSource = $Variables.Workers | Select-Object @(
+ @{ Name = "Worker"; Expression = { $_.worker } },
+ @{ Name = "Status"; Expression = { $_.status } },
+ @{ Name = "Last seen"; Expression = { $_.TimeSinceLastReportText } },
+ @{ Name = "Version"; Expression = { $_.version } },
+ @{ Name = "Est. Profit $($Config.Currency)/day"; Expression = { [Decimal]($_.Profit * ($Variables.Rates.BTC.($Config.Currency))) } },
+ @{ Name = "Miner"; Expression = { $_.data.Name -join $nl } },
+ @{ Name = "Pool"; Expression = { ($_.data | ForEach-Object { ($_.Pool -join " & ") } -join $nl) } },
+ @{ Name = "Algorithm"; Expression = { ($_.data | ForEach-Object { $_.Algorithm -split "," -join " & " }) -join $nl } },
+ @{ Name = "Live Hashrate"; Expression = { If ($_.data.CurrentSpeed) { ($_.data | ForEach-Object { ($_.CurrentSpeed | ForEach-Object { "$($_ | ConvertTo-Hash)/s" -replace "\s+", " " }) -join " & " }) -join $nl } Else { "" } } },
+ @{ Name = "Benchmark Hashrate"; Expression = { If ($_.data.EstimatedSpeed) { ($_.data | ForEach-Object { ($_.EstimatedSpeed | ForEach-Object { "$($_ | ConvertTo-Hash)/s" -replace "\s+", " " }) -join " & " }) -join $nl } Else { "" } } }
+ ) | Sort-Object "Worker" | Out-DataTable
+
+ # Set row color
+ ForEach ($Row in $WorkersDGV.Rows) {
+ $Row.DefaultCellStyle.Backcolor = Switch ($Row.DataBoundItem.Status) {
+ "Offline" { [System.Drawing.Color]::FromArgb(255, 255, 230, 230) }
+ "Paused" { [System.Drawing.Color]::FromArgb(255, 255, 241, 195) }
+ "Running" { [System.Drawing.Color]::FromArgb(255, 232, 250, 232) }
+ Default { [System.Drawing.Color]::FromArgb(255, 255, 255, 255) }
+ }
+ }
+
+ If ($WorkersDGV.Columns) {
+ $WorkersDGV.Columns[0].FillWeight = 70
+ $WorkersDGV.Columns[1].FillWeight = 40
+ $WorkersDGV.Columns[2].FillWeight = 80
+ $WorkersDGV.Columns[3].FillWeight = 70
+ $WorkersDGV.Columns[4].FillWeight = 65
+ $WorkersDGV.Columns[5].FillWeight = 175
+ $WorkersDGV.Columns[6].FillWeight = 95
+ $WorkersDGV.Columns[7].FillWeight = 75
+ $WorkersDGV.Columns[8].FillWeight = 65
+ $WorkersDGV.Columns[9].FillWeight = 65
+ }
+
+ $WorkersDGV.ClearSelection()
+
+ $LabelWorkers.Text = "Worker Status - Updated $($Variables.WorkersLastUpdated.ToString())"
+ }
+ Else { $LabelWorkers.Text = "Worker Status - no workers" }
+ }
+ "Benchmarks" {
+ If ($Variables.Miners) {
+ If ($Variables.CalculatePowerCost -and -not $Config.IgnorePowerCost) { $SortBy = "Profit" } Else { $SortBy = "Earning" }
+ $BenchmarksDGV.DataSource = $Variables.Miners | Where-Object Available -EQ $true | Select-Object @(
+ @{ Name = "Miner"; Expression = { $_.Name } },
+ @{ Name = "Device(s)"; Expression = { $_.DeviceName -join '; ' } },
+ @{ Name = "Algorithm"; Expression = { $_.Algorithm -join ' & ' } },
+ @{ Name = "PowerUsage"; Expression = { If ($_.MeasurePowerUsage) { "Measuring" } Else { "$($_.PowerUsage.ToString("N3")) W" } } },
+ @{ Name = "Hashrate"; Expression = { ($_.Workers.Speed | ForEach-Object { If (-not [Double]::IsNaN($_)) { "$($_ | ConvertTo-Hash)/s" -replace '\s+', ' ' } Else { "Benchmarking" } }) -join ' & ' } },
+ @{ Name = "Earning $($Config.Currency)/day"; Expression = { If (-not [Double]::IsNaN($_.Earning)) { ($_.Earning * $Variables.Rates.BTC.($Config.Currency)).ToString("N3") } Else { "Unknown" } } },
+ @{ Name = "Profit $($Config.Currency)/day"; Expression = { If ($Variables.CalculatePowerCost -and -not [Double]::IsNaN($_.Profit)) { ($_.Profit * $Variables.Rates.BTC.($Config.Currency)).ToString("N3") } Else { "Unknown" } } },
+ @{ Name = "Pool"; Expression = { ($_.Workers.Pool | ForEach-Object { (@(@($_.Name | Select-Object) + @($_.Coin | Select-Object))) -join '-' }) -join ' & ' } }
+ ) | Sort-Object "$SortBy $($Config.Currency)/day" -Descending | Out-DataTable
+ Remove-Variable SortBy
+
+ $BenchmarksDGV.ClearSelection()
+
+ If ($BenchmarksDGV.Columns) {
+ $BenchmarksDGV.Columns[0].FillWeight = 220
+ $BenchmarksDGV.Columns[1].FillWeight = 80
+ $BenchmarksDGV.Columns[2].FillWeight = 90
+ $BenchmarksDGV.Columns[3].FillWeight = 70
+ $BenchmarksDGV.Columns[4].FillWeight = 100
+ $BenchmarksDGV.Columns[5].FillWeight = 55
+ $BenchmarksDGV.Columns[6].FillWeight = 55
+ $BenchmarksDGV.Columns[7].FillWeight = 125
+ }
+ $LabelBenchmarks.Text = "Benchmark data read from stats - Updated $((Get-Date).ToString())"
+ }
+ Else { $LabelBenchmarks.Text = "Waiting for data..." }
+ }
+ }
+
+ $Mainform.Cursor = [System.Windows.Forms.Cursors]::Normal
+
+}
+
+Function Global:TimerUITick {
+ $TimerUI.Enabled = $false
+
+ $Variables.LogFile = "$($Variables.MainPath)\Logs\$($Variables.Branding.ProductLabel)_$(Get-Date -Format "yyyy-MM-dd").log"
+
+ # If something (pause button, idle timer, WebGUI/config) has set the RestartCycle flag, stop and start mining to switch modes immediately
+ If ($Variables.RestartCycle) {
+
+ $Variables.RestartCycle = $false
+
+ If ($Variables.NewMiningStatus -ne $Variables.MiningStatus) {
+ $ButtonPause.Enabled = $false
+ $ButtonStart.Enabled = $false
+ $ButtonStop.Enabled = $false
+
+ Switch ($Variables.NewMiningStatus) {
+ "Idle" {
+ If ($Variables.MiningStatus) {
+ $Variables.Summary = "Stopping $($Variables.Branding.ProductLabel) ('Stop mining' button pressed)..."
+ Write-Message -Level Info $Variables.Summary
+ }
+ Stop-Mining
+ Stop-BrainJob
+ Stop-IdleDetection
+ Stop-BalancesTracker
+ Send-MonitoringData
+
+ $LabelMiningStatus.Text = "Stopped | $($Variables.Branding.ProductLabel) $($Variables.Branding.Version)"
+ $LabelMiningStatus.ForeColor = [System.Drawing.Color]::Red
+
+ $Variables.Summary = "$($Variables.Branding.ProductLabel) is idle."
+ Write-Host "`n"
+ Write-Message -Level Info $Variables.Summary
+
+ $ButtonPause.Enabled = $true
+ $ButtonStart.Enabled = $true
+ }
+ "Paused" {
+ $TimerUI.Stop
+
+ If ($Variables.MiningStatus) {
+ $Variables.Summary = "Pausing $($Variables.Branding.ProductLabel) ('Pause mining' button pressed)..."
+ Write-Message -Level Info $Variables.Summary
+ }
+
+ If ($Variables.MiningStatus -eq "Running") {
+ Stop-Mining
+ Stop-BrainJob
+ Stop-IdleDetection
+ }
+ Else {
+ Initialize-Application
+ Start-BalancesTracker
+ }
+ Send-MonitoringData
+
+ $LabelMiningStatus.Text = "Paused | $($Variables.Branding.ProductLabel) $($Variables.Branding.Version)"
+ $LabelMiningStatus.ForeColor = [System.Drawing.Color]::Blue
+
+ $Variables.Summary = "$($Variables.Branding.ProductLabel) is paused."
+ Write-Host "`n"
+ Write-Message -Level Info $Variables.Summary
+
+ $ButtonStop.Enabled = $true
+ $ButtonStart.Enabled = $true
+ }
+ "Running" {
+ If ($Variables.MiningStatus) {
+ $Variables.Summary = "Starting $($Variables.Branding.ProductLabel) ('Start mining' button pressed)..."
+ Write-Message -Level Info $Variables.Summary
+ }
+
+ Initialize-Application
+ Start-BalancesTracker
+ Start-Mining
+
+ $LabelMiningStatus.Text = "Running | $($Variables.Branding.ProductLabel) $($Variables.Branding.Version)"
+ $LabelMiningStatus.ForeColor = [System.Drawing.Color]::Green
+
+ $Variables.Summary = "$($Variables.Branding.ProductLabel) is running."
+ Write-Host "`n"
+ Write-Message -Level Info $Variables.Summary
+
+ $ButtonStop.Enabled = $true
+ $ButtonStart.Enabled = $false
+ $ButtonPause.Enabled = $true
+ }
+ }
+
+ $Variables.MiningStatus = $Variables.NewMiningStatus
+ }
+ }
+
+ If ($Variables.RefreshNeeded -and $Variables.MiningStatus -eq "Running") {
+ $host.UI.RawUI.WindowTitle = $MainForm.Text = "$($Variables.Branding.ProductLabel) $($Variables.Branding.Version) Runtime: {0:dd} days {0:hh} hrs {0:mm} mins Path: $($Variables.Mainpath)" -f [TimeSpan]((Get-Date).ToUniversalTime() - $Variables.ScriptStartTime)
+
+ If (-not ($Variables.Miners | Where-Object Status -eq "Running")) { Write-Message -Level Info "No miners running. Waiting for next cycle." }
+
+ # Refresh selected tab
+ Update-TabControl
+
+ $LabelEarningsDetails.Lines = @($Variables.Summary -replace " |( )+", "`n" -replace " / ", "/" -split "`n")
+
+ Clear-Host
+
+ # Get and display earnings stats
+ If ($Variables.Balances -and $Variables.ShowPoolBalances) {
+ $Variables.Balances.Values | ForEach-Object {
+ If ($_.Currency -eq "BTC" -and $Config.UsemBTC) { $Currency = "mBTC"; $mBTCfactor = 1000 } Else { $Currency = $_.Currency; $mBTCfactor = 1 }
+ Write-Host "$($_.Pool -replace ' Internal$', ' (Internal Wallet)' -replace ' External$', ' (External Wallet)') [$($_.Wallet)]" -ForegroundColor Green
+ Write-Host "Earned last hour: $(($_.Growth1 * $mBTCfactor).ToString('N8')) $Currency / $(($_.Growth1 * $Variables.Rates.($_.Currency).($Config.Currency)).ToString('N8')) $($Config.Currency)"
+ Write-Host "Earned last 24 hours: $(($_.Growth24 * $mBTCfactor).ToString('N8')) $Currency / $(($_.Growth24 * $Variables.Rates.($_.Currency).($Config.Currency)).ToString('N8')) $($Config.Currency)"
+ Write-Host "Earned last 7 days: $(($_.Growth168 * $mBTCfactor).ToString('N8')) $Currency / $(($_.Growth168 * $Variables.Rates.($_.Currency).($Config.Currency)).ToString('N8')) $($Config.Currency)"
+ Write-Host "≈ average / hour: $(($_.AvgHourlyGrowth * $mBTCfactor).ToString('N8')) $Currency / $(($_.AvgHourlyGrowth * $Variables.Rates.($_.Currency).($Config.Currency)).ToString('N8')) $($Config.Currency)"
+ Write-Host "≈ average / day: $(($_.AvgDailyGrowth * $mBTCfactor).ToString('N8')) $Currency / $(($_.AvgDailyGrowth * $Variables.Rates.($_.Currency).($Config.Currency)).ToString('N8')) $($Config.Currency)"
+ Write-Host "≈ average / week: $(($_.AvgWeeklyGrowth * $mBTCfactor).ToString('N8')) $Currency / $(($_.AvgWeeklyGrowth * $Variables.Rates.($_.Currency).($Config.Currency)).ToString('N8')) $($Config.Currency)"
+ Write-Host "Balance: " -NoNewline; Write-Host "$(($_.Balance * $mBTCfactor).ToString('N8')) $Currency / $(($_.Balance * $Variables.Rates.($_.Currency).($Config.Currency)).ToString('N8')) $($Config.Currency)" -ForegroundColor Yellow
+ Write-Host " $(($_.Balance / $_.PayoutThreshold * $mBTCFactor).ToString('P1')) of $($_.PayoutThreshold.ToString()) $($_.PayoutThresholdCurrency) payment threshold"
+ Write-Host "Projected Payment Date: $(If ($_.ProjectedPayDate -is [DateTime]) { $_.ProjectedPayDate.ToString("G") } Else { $_.ProjectedPayDate })`n"
+ }
+ Remove-Variable Currency -ErrorAction Ignore
+ }
+ If ($Variables.MinersMissingBinary) {
+ Write-Host "`n"
+ Write-Host "Some miners binaries are missing, downloader is installing miner binaries..." -ForegroundColor Yellow
+ }
+
+ If ($Variables.Miners | Where-Object Available -EQ $true | Where-Object { $_.Benchmark -eq $true -or $_.MeasurePowerUsage -eq $true }) {
+ If ($Config.UIStyle -ne "Full") {
+ $Variables.UIStyle = "Full"
+ Write-Host "Benchmarking / Measuring power usage: Temporarily switched UI style to 'Full' (Information about miners run in the past, failed miners & watchdog timers will $(If ($Variables.UIStyle -eq "Light") { "not " })be shown)" -ForegroundColor Yellow
+ }
+ }
+ Else {
+ $Variables.UIStyle = $Config.UIStyle
+ }
+
+ # Display available miners list
+ [System.Collections.ArrayList]$Miner_Table = @(
+ @{ Label = "Miner"; Expression = { $_.Name } }
+ @{ Label = "Algorithm"; Expression = { $_.Workers.Pool.Algorithm -join " & " } }
+ If ($Variables.ShowMinerFee -and ($Variables.Miners.Workers.Fee)) { @{ Label = "Fee"; Expression = { $_.Workers.Fee | ForEach-Object { "{0:P2}" -f [Double]$_ } } } }
+ @{ Label = "Hashrate"; Expression = { If (-not $_.Benchmark) { $_.Workers | ForEach-Object { "$($_.Speed | ConvertTo-Hash)/s" } } Else { If ($_.Status -eq "Running") { "Benchmarking..." } Else { "Benchmark pending" } } }; Align = "right" }
+ If (-not $Config.IgnorePowerCost -and $Variables.ShowProfitBias -and $Config.CalculatePowerCost -and $Variables.MiningPowerCost -and -not $Config.IgnorePowerCost) { @{ Label = "ProfitBias"; Expression = { If (-not [Double]::IsNaN($_.Profit_Bias)) { ConvertTo-LocalCurrency -Value $_.Profit_Bias -Rate $Variables.Rates.BTC.($Config.Currency) -Offset 1 } Else { "Unknown" } }; Align = "right" } }
+ If (-not $Config.IgnorePowerCost -and $Variables.ShowProfit -and $Config.CalculatePowerCost -and $Variables.MiningPowerCost -and -not $Config.IgnorePowerCost) { @{ Label = "Profit"; Expression = { If (-not [Double]::IsNaN($_.Profit)) { ConvertTo-LocalCurrency -Value $_.Profit -Rate $Variables.Rates.BTC.($Config.Currency) -Offset 1 } Else { "Unknown" } }; Align = "right" } }
+ If ($Variables.ShowEarningBias) { @{ Label = "EarningBias"; Expression = { If (-not [Double]::IsNaN($_.Earning_Bias)) { ConvertTo-LocalCurrency -Value $_.Earning_Bias -Rate $Variables.Rates.BTC.($Config.Currency) -Offset 1 } Else { "Unknown" } }; Align = "right" } }
+ If ($Variables.ShowEarning) { @{ Label = "Earning"; Expression = { If (-not [Double]::IsNaN($_.Earning)) { ConvertTo-LocalCurrency -Value $_.Earning -Rate $Variables.Rates.BTC.($Config.Currency) -Offset 1 } Else { "Unknown" } }; Align = "right" } }
+ If ($Config.IgnorePowerCost -and $Variables.ShowProfitBias -and $Config.CalculatePowerCost -and $Variables.MiningPowerCost) { @{ Label = "ProfitBias"; Expression = { If (-not [Double]::IsNaN($_.Profit_Bias)) { ConvertTo-LocalCurrency -Value $_.Profit_Bias -Rate $Variables.Rates.BTC.($Config.Currency) -Offset 1 } Else { "Unknown" } }; Align = "right" } }
+ If ($Config.IgnorePowerCost -and $Variables.ShowProfit -and $Config.CalculatePowerCost -and $Variables.MiningPowerCost) { @{ Label = "Profit"; Expression = { If (-not [Double]::IsNaN($_.Profit)) { ConvertTo-LocalCurrency -Value $_.Profit -Rate $Variables.Rates.BTC.($Config.Currency) -Offset 1 } Else { "Unknown" } }; Align = "right" } }
+ If ($Variables.ShowPowerUsage -and $Config.CalculatePowerCost) { @{ Label = "PowerUsage"; Expression = { If (-not $_.MeasurePowerUsage) { "$($_.PowerUsage.ToString("N2")) W" } Else { If ($_.Status -eq "Running") { "Measuring..." } Else { "Unmeasured" } } }; Align = "right" } }
+ If ($Variables.ShowPowerCost -and $Config.CalculatePowerCost -and $Variables.MiningPowerCost) { @{ Label = "PowerCost"; Expression = { If ($Variables.PowerPricekWh -eq 0) { (0).ToString("N$(Get-DigitsFromValue -Value $Variables.Rates.BTC.($Config.Currency) -Offset 1)") } Else { If (-not [Double]::IsNaN($_.PowerUsage)) { "-$(ConvertTo-LocalCurrency -Value ($_.PowerCost) -Rate ($Variables.Rates.($Config.PayoutCurrency).($Config.Currency)) -Offset 1)" } Else { "Unknown" } } }; Align = "right" } }
+ If ($Variables.ShowAccuracy) { @{ Label = "Accuracy"; Expression = { $_.Workers.Pool.Accuracy | ForEach-Object { "{0:P0}" -f [Double]$_ } }; Align = "right" } }
+ @{ Label = "Pool"; Expression = { $_.Workers.Pool.Name -join " & " } }
+ If ($Variables.ShowPoolFee -and ($Variables.Miners.Workers.Pool.Fee)) { @{ Label = "Fee"; Expression = { $_.Workers.Pool.Fee | ForEach-Object { "{0:P2}" -f [Double]$_ } } } }
+ If ($Variables.ShowCurrency -and $Variables.Miners.Workers.Pool.Currency) { @{ Label = "Currency"; Expression = { "$(If ($_.Workers.Pool.Currency) { $_.Workers.Pool.Currency })" -replace '{, }' } } }
+ If ($Variables.ShowCoinName -and $Variables.Miners.Workers.Pool.CoinName) { @{ Label = "CoinName"; Expression = { "$(If ($_.Workers.Pool.CoinName) { $_.Workers.Pool.CoinName })" -replace '{, }' } } }
+ )
+ If ($Variables.CalculatePowerCost) { $SortBy = "Profit" } Else { $SortBy = "Earning" }
+ $Variables.Miners | Where-Object Available -EQ $true | Group-Object -Property { [String]$_.DeviceName } | Sort-Object Name | ForEach-Object {
+ $MinersDeviceGroup = @($_.Group)
+ $MinersDeviceGroupNeedingBenchmark = @($MinersDeviceGroup | Where-Object Benchmark -EQ $true)
+ $MinersDeviceGroupNeedingPowerUsageMeasurement = @($MinersDeviceGroup | Where-Object Enabled -EQ $True | Where-Object MeasurePowerUsage -EQ $true)
+ $MinersDeviceGroup = @($MinersDeviceGroup | Where-Object { $Variables.ShowAllMiners -or $_.MostProfitable -eq $true -or $MinersDeviceGroupNeedingBenchmark.Count -gt 0 -or $MinersDeviceGroupNeedingPowerUsageMeasurement.Count -gt 0 })
+ $MinersDeviceGroup | Where-Object {
+ $Variables.ShowAllMiners -or <#List all miners#>
+ $MinersDeviceGroupNeedingBenchmark.Count -gt 0 -or <#List all miners when benchmarking#>
+ $MinersDeviceGroupNeedingPowerUsageMeasurement.Count -gt 0 -or <#List all miners when measuring power usage#>
+ $_.$SortBy -ge ($MinersDeviceGroup.$SortBy | Sort-Object -Descending | Select-Object -Index (($MinersDeviceGroup.Count, 5 | Measure-Object -Minimum).Minimum - 1)) -or <#Always list at least the top 5 miners per device group#>
+ $_.$SortBy -ge (($MinersDeviceGroup.$SortBy | Sort-Object -Descending | Select-Object -First 1) * 0.5) <#Always list the better 50% miners per device group#>
+ } | Sort-Object -Property DeviceName, @{ Expression = { $_.Benchmark -eq $true }; Descending = $true }, @{ Expression = { $_.MeasurePowerUsage -eq $true }; Descending = $true }, @{ Expression = { $_.KeepRunning -eq $true }; Descending = $true }, @{ Expression = { $_.Prioritize -eq $true }; Descending = $true }, @{ Expression = { $_."$($SortBy)_Bias" }; Descending = $true }, @{ Expression = { $_.Name }; Descending = $false }, @{ Expression = { $_.Algorithm[0] }; Descending = $false }, @{ Expression = { $_.Algorithm[1] }; Descending = $false } |
+ Format-Table $Miner_Table -GroupBy @{ Name = "Device$(If (@($_).Count -ne 1) { "s" })"; Expression = { "$($_.DeviceName -join ', ') [$(($Variables.Devices | Where-Object Name -In $_.DeviceName).Model -join ', ')]" } } | Out-Host
+
+ # Display benchmarking progress
+ If ($MinersDeviceGroupNeedingBenchmark) {
+ "Benchmarking for device$(If (($MinersDeviceGroup.DeviceName | Select-Object -Unique).Count -gt 1) { " group" }) '$(($MinersDeviceGroup.DeviceName | Sort-Object -Unique) -join '; ')' in progress: $($MinersDeviceGroupNeedingBenchmark.Count) miner$(If ($MinersDeviceGroupNeedingBenchmark.Count -gt 1){ 's' }) left to complete benchmark." | Out-Host
+ }
+ # Display power usage measurement progress
+ If ($MinersDeviceGroupNeedingPowerUsageMeasurement) {
+ "Power usage measurement for device$(If (($MinersDeviceGroup.DeviceName | Select-Object -Unique).Count -gt 1) { " group" }) '$(($MinersDeviceGroup.DeviceName | Sort-Object -Unique) -join '; ')' in progress: $($MinersDeviceGroupNeedingPowerUsageMeasurement.Count) miner$(If ($MinersDeviceGroupNeedingPowerUsageMeasurement.Count -gt 1) { 's' }) left to complete measuring." | Out-Host
+ }
+ }
+
+ If ($ProcessesRunning = @($Variables.Miners | Where-Object { $_.Status -eq "Running" })) {
+ Write-Host "Running $(If ($ProcessesRunning.Count -eq 1) { "miner:" } Else { "miners: $($ProcessesRunning.Count)" })"
+ [System.Collections.ArrayList]$Miner_Table = @(
+ @{ Label = "Hashrate"; Expression = { If ($_.Speed_Live) { (($_.Speed_Live | ForEach-Object { "$($_ | ConvertTo-Hash)/s" }) -join ' & ') -replace '\s+', ' ' } Else { "n/a" } }; Align = "right" }
+ If ($Variables.ShowPowerUsage) { @{ Label = "PowerUsage"; Expression = { If ($_.PowerUsage_Live) { "$($_.PowerUsage_Live.ToString("N2")) W" } Else { "n/a" } }; Align = "right" } }
+ @{ Label = "Active (this run)"; Expression = { "{0:dd}d {0:hh}h {0:mm}m {0:ss}s" -f ((Get-Date).ToUniversalTime() - $_.BeginTime) } }
+ @{ Label = "Active (total)"; Expression = { "{0:dd}d {0:hh}h {0:mm}m {0:ss}s" -f ($_.TotalMiningDuration) } }
+ @{ Label = "Cnt"; Expression = { Switch ($_.Activated) { 0 { "Never" } 1 { "Once" } Default { "$_" } } } }
+ @{ Label = "Device"; Expression = { $_.DeviceName -join '; ' } }
+ @{ Label = "Name"; Expression = { $_.Name -join '; ' } }
+ @{ Label = "Command"; Expression = { "$($_.Path.TrimStart((Convert-Path ".\"))) $(Get-CommandLineParameters $_.Arguments)" } }
+ )
+ $ProcessesRunning | Sort-Object DeviceName | Format-Table $Miner_Table -Wrap | Out-Host
+ }
+
+ If ($Variables.UIStyle -eq "Full") {
+ If ($ProcessesIdle = @($Variables.Miners | Where-Object { $_.Activated -and $_.Status -eq "Idle" -and $_.GetActiveLast().ToLocalTime().AddHours(24) -gt (Get-Date) })) {
+ Write-Host " $($ProcessesIdle.Count) previously executed $(If ($ProcessesIdle.Count -eq 1) { "miner" } Else { "miners" }) in the past 24 hrs:"
+ [System.Collections.ArrayList]$Miner_Table = @(
+ @{ Label = "Hashrate"; Expression = { (($_.Workers.Speed | ForEach-Object { If (-not [Double]::IsNaN($_)) { "$($_ | ConvertTo-Hash)/s" } Else { "n/a" } }) -join ' & ') -replace '\s+', ' ' }; Align = "right" }
+ If ($Variables.ShowPowerUsage) { @{ Label = "PowerUsage"; Expression = { If (-not [Double]::IsNaN($_.PowerUsage)) { "$($_.PowerUsage.ToString("N2")) W" } Else { "n/a" } }; Align = "right" } }
+ @{ Label = "Time since last run"; Expression = { "{0:dd}d {0:hh}h {0:mm}m {0:ss}s" -f $((Get-Date) - $_.GetActiveLast().ToLocalTime()) } }
+ @{ Label = "Active (total)"; Expression = { "{0:dd}d {0:hh}h {0:mm}m {0:ss}s" -f $_.TotalMiningDuration } }
+ @{ Label = "Cnt"; Expression = { Switch ($_.Activated) { 0 { "Never" } 1 { "Once" } Default { "$_" } } } }
+ @{ Label = "Device"; Expression = { $_.DeviceName -join '; ' } }
+ @{ Label = "Name"; Expression = { $_.Name -join '; ' } }
+ @{ Label = "Command"; Expression = { "$($_.Path.TrimStart((Convert-Path ".\"))) $(Get-CommandLineParameters $_.Arguments)" } }
+ )
+ $ProcessesIdle | Sort-Object { $_.GetActiveLast } -Descending | Select-Object -First ($MinersDeviceGroup.Count * 3) | Format-Table $Miner_Table | Out-Host
+ }
+
+ If ($ProcessesFailed = @($Variables.Miners | Where-Object { $_.Activated -and $_.Status -eq "Failed" -and $_.GetActiveLast().ToLocalTime().AddHours(24) -gt (Get-Date)})) {
+ Write-Host -ForegroundColor Red "$($ProcessesFailed.Count) failed $(If ($ProcessesFailed.Count -eq 1) { "miner" } Else { "miners" }) in the past 24 hrs:"
+ [System.Collections.ArrayList]$Miner_Table = @(
+ @{ Label = "Hashrate"; Expression = { (($_.Workers.Speed | ForEach-Object { If (-not [Double]::IsNaN($_)) { "$($_ | ConvertTo-Hash)/s" } Else { "n/a" } }) -join ' & ') -replace '\s+', ' ' }; Align = "right" }
+ If ($Variables.ShowPowerUsage) { @{ Label = "PowerUsage"; Expression = { If (-not [Double]::IsNaN($_.PowerUsage)) { "$($_.PowerUsage.ToString("N2")) W" } Else { "n/a" } }; Align = "right" } }
+ @{ Label = "Time since last fail"; Expression = { "{0:dd}d {0:hh}h {0:mm}m {0:ss}s" -f $((Get-Date) - $_.GetActiveLast().ToLocalTime()) } }
+ @{ Label = "Active (total)"; Expression = { "{0:dd}d {0:hh}h {0:mm}m {0:ss}s" -f $_.TotalMiningDuration } }
+ @{ Label = "Cnt"; Expression = { Switch ($_.Activated) { 0 { "Never" } 1 { "Once" } Default { "$_" } } } }
+ @{ Label = "Device"; Expression = { $_.DeviceName -join '; ' } }
+ @{ Label = "Name"; Expression = { $_.Name -join '; ' } }
+ @{ Label = "Command"; Expression = { "$($_.Path.TrimStart((Convert-Path ".\"))) $(Get-CommandLineParameters $_.Arguments)" } }
+ )
+ $ProcessesFailed | Sort-Object { If ($_.Process) { $_.Process.StartTime } Else { [DateTime]0 } } | Format-Table $Miner_Table -Wrap | Out-Host
+ }
+
+ If ($Config.Watchdog -eq $true) {
+ # Display watchdog timers
+ $Variables.WatchdogTimers | Where-Object Kicked -GT $Variables.Timer.AddSeconds(-$Variables.WatchdogReset) | Format-Table -Wrap (
+ @{Label = "Miner Watchdog Timers"; Expression = { $_.MinerName } },
+ @{Label = "Pool"; Expression = { $_.PoolName } },
+ @{Label = "Algorithm"; Expression = { $_.Algorithm } },
+ @{Label = "Device"; Expression = { $_.DeviceName } },
+ @{Label = "Last Updated"; Expression = { "{0:mm} min {0:ss} sec ago" -f ((Get-Date).ToUniversalTime() - $_.Kicked) }; Align = "right" }
+ ) | Out-Host
+ }
+ }
+
+ Remove-Variable SortBy
+ Remove-Variable MinersDeviceGroup -ErrorAction SilentlyContinue
+ Remove-Variable MinersDeviceGroupNeedingBenchmark -ErrorAction SilentlyContinue
+ Remove-Variable MinersDeviceGroupNeedingPowerUsageMeasurement -ErrorAction SilentlyContinue
+ Remove-Variable Miner_Table -ErrorAction SilentlyContinue
+
+ $Variables.Summary -split ' ' | ForEach-Object { Write-Host ($_ -replace " ", " " -replace "'/ ", "/") }
+
+ If (-not $Variables.Paused) {
+ If ($Variables.Miners | Where-Object Available -EQ $true | Where-Object { $_.Benchmark -eq $false -or $_.MeasurePowerUsage -eq $false }) {
+ If ($Variables.MiningEarning -lt $Variables.MiningPowerCost) {
+ # Mining causes a loss
+ Write-Host -ForegroundColor Red "Mining is currently NOT profitable and causes a loss of $($Config.Currency) $((($Variables.MiningProfit - $Variables.BasePowerCostBTC) * $Variables.Rates.BTC.($Config.Currency)).ToString("N$(Get-DigitsFromValue -Value $Variables.Rates.($Config.PayoutCurrency).($Config.Currency) -Offset 1)"))/day (including Base Power Cost)."
+ }
+ If (($Variables.MiningEarning - $Variables.MiningPowerCost) -lt $Config.ProfitabilityThreshold) {
+ # Mining profit is below the configured threshold
+ Write-Host -ForegroundColor Blue "Mining profit ($($Config.Currency) $(ConvertTo-LocalCurrency -Value ($Variables.MiningProfit - $Variables.BasePowerCostBTC) -Rate $Variables.Rates.BTC.($Config.Currency) -Offset 1)) is below the configured threshold of $($Config.Currency) $($Config.ProfitabilityThreshold.ToString("N$((Get-Culture).NumberFormat.CurrencyDecimalDigits)"))/day; mining is suspended until threshold is reached."
+ }
+ }
+ }
+
+ $StatusMessage = "Last refresh: $($Variables.Timer.ToLocalTime().ToString('G')) | Next refresh: $($Variables.EndLoopTime.ToLocalTime().ToString('G')) | Hot Keys: $(If ($Variables.CalculatePowerCost) { "[abceilmnprstuy]" } Else { "[abeilmnpsy]" }) | Press 'h' for help"
+ Write-Host ("-" * $StatusMessage.Length)
+ Write-Host -ForegroundColor Yellow $StatusMessage
+ Remove-Variable StatusMessage
+
+ $Variables.RefreshNeeded = $false
+ }
+ $TimerUI.Start()
+}
+
+Function MainForm_Load {
+ $MainForm.Text = "$($Variables.Branding.ProductLabel) $($Variables.Branding.Version)"
+ $LabelMiningStatus.Text = "$($Variables.Branding.ProductLabel) $($Variables.Branding.Version)"
+ $MainForm.Number = 0
+ $TimerUI.Add_Tick(
+ {
+ # Display mining information
+ If ($host.UI.RawUI.KeyAvailable) {
+ $KeyPressed = $host.UI.RawUI.ReadKey("NoEcho, IncludeKeyDown, IncludeKeyUp"); Start-Sleep -Milliseconds 300; $host.UI.RawUI.FlushInputBuffer()
+ If ($KeyPressed.KeyDown) {
+ Switch ($KeyPressed.Character) {
+ "a" {
+ $Variables.ShowAccuracy = -not $Variables.ShowAccuracy
+ Write-Host "Toggled displaying " -NoNewline; Write-Host "A" -ForegroundColor Cyan -NoNewline; Write-Host "ccuracy to " -NoNewline; If ($Variables.ShowAccuracy) { Write-Host "on" -ForegroundColor Green -NoNewline } Else { Write-Host "off" -ForegroundColor Red -NoNewline }; Write-Host "."
+ $Variables.RefreshNeeded = $true
+ Start-Sleep -Seconds 2
+ }
+ "b" {
+ $Variables.ShowPoolBalances = -not $Variables.ShowPoolBalances
+ Write-Host "Toggled displaying Pool " -NoNewline; Write-Host "B" -ForegroundColor Cyan -NoNewline; Write-Host "alances to " -NoNewline; If ($Variables.ShowPoolBalances) { Write-Host "on" -ForegroundColor Green -NoNewline } Else { Write-Host "off" -ForegroundColor Red -NoNewline }; Write-Host "."
+ $Variables.RefreshNeeded = $true
+ Start-Sleep -Seconds 2
+ }
+ "c" {
+ If ($Variables.CalculatePowerCost) {
+ $Variables.ShowPowerCost = -not $Variables.ShowPowerCost
+ Write-Host "Toggled displaying Power " -NoNewline; Write-Host "C" -ForegroundColor Cyan -NoNewline; Write-Host "ost to " -NoNewline; If ($Variables.ShowPowerCost) { Write-Host "on" -ForegroundColor Green -NoNewline } Else { Write-Host "off" -ForegroundColor Red -NoNewline }; Write-Host "."
+ $Variables.RefreshNeeded = $true
+ Start-Sleep -Seconds 2
+ }
+ }
+ "e" {
+ $Variables.ShowEarning = -not $Variables.ShowEarning
+ Write-Host "Toggled displaying " -NoNewline; Write-Host "E" -ForegroundColor Cyan -NoNewline; Write-Host "arnings to " -NoNewline; If ($Variables.ShowEarning) { Write-Host "on" -ForegroundColor Green -NoNewline } Else { Write-Host "off" -ForegroundColor Red -NoNewline }; Write-Host "."
+ $Variables.RefreshNeeded = $true
+ Start-Sleep -Seconds 2
+ }
+ "h" {
+ Write-Host "Hot key legend:"
+ Write-Host "a: Toggle " -NoNewline; Write-Host "A" -ForegroundColor Cyan -NoNewline; Write-Host "ccuracy column"
+ Write-Host "b: Toggle Pool " -NoNewline; Write-Host "B" -ForegroundColor Cyan -NoNewline; Write-Host "alances"
+ If ($Variables.CalculatePowerCost) {
+ Write-Host "c: Toggle Power " -NoNewline; Write-Host "C" -ForegroundColor Cyan -NoNewline; Write-Host "ost column"
+ }
+ Write-Host "e: Toggle " -NoNewline; Write-Host "E" -ForegroundColor Cyan -NoNewline; Write-Host "arnings column"
+ Write-Host "i: Toggle Earning B" -NoNewline; Write-Host "i" -ForegroundColor Cyan -NoNewline; Write-Host "as column"
+ Write-Host "l: Toggle listing al" -NoNewline; Write-Host "l" -ForegroundColor Cyan -NoNewline; Write-Host " available miners"
+ Write-Host "m: Toggle " -NoNewline; Write-Host "M" -ForegroundColor Cyan -NoNewline; Write-Host "iner Fees column"
+ Write-Host "n: Toggle Coin" -NoNewline; Write-Host "N" -ForegroundColor Cyan -NoNewline; Write-Host "ame column"
+ Write-Host "p: Toggle " -NoNewline; Write-Host "P" -ForegroundColor Cyan -NoNewline; Write-Host "ool Fees column"
+ If ($Variables.CalculatePowerCost) {
+ Write-Host "r: Toggle P" -NoNewline; Write-Host "r" -ForegroundColor Cyan -NoNewline; Write-Host "ofit Bias column"
+ }
+ Write-Host "s: Toggle " -NoNewline; Write-Host "S" -ForegroundColor Cyan -NoNewline; Write-Host "tyle (full or light)"
+ If ($Variables.CalculatePowerCost) {
+ Write-Host "t: Toggle Profi" -NoNewline; Write-Host "t" -ForegroundColor Cyan -NoNewline; Write-Host " column"
+ Write-Host "u: Toggle Power " -NoNewline; Write-Host "U" -ForegroundColor Cyan -NoNewline; Write-Host "sage column"
+ }
+ Write-Host "y: Toggle Currenc" -NoNewline; Write-Host "y" -ForegroundColor Cyan -NoNewline; Write-Host " column"
+ }
+ "i" {
+ $Variables.ShowEarningBias = -not $Variables.ShowEarningBias
+ Write-Host "Toggled displaying Earning B" -NoNewline; Write-Host "i" -ForegroundColor Cyan -NoNewline; Write-Host "as to " -NoNewline; If ($Variables.ShowEarningBias) { Write-Host "on" -ForegroundColor Green -NoNewline } Else { Write-Host "off" -ForegroundColor Red -NoNewline }; Write-Host "."
+ $Variables.RefreshNeeded = $true
+ Start-Sleep -Seconds 2
+ }
+ "l" {
+ $Variables.ShowAllMiners = -not $Variables.ShowAllMiners
+ Write-Host "Toggled displaying Al" -NoNewline; Write-Host "l" -ForegroundColor Cyan -NoNewline; Write-Host " available miners to " -NoNewline; If ($Variables.ShowAllMiners) { Write-Host "on" -ForegroundColor Green -NoNewline } Else { Write-Host "off" -ForegroundColor Red -NoNewline }; Write-Host "."
+ $Variables.RefreshNeeded = $true
+ Start-Sleep -Seconds 2
+ }
+ "m" {
+ $Variables.ShowMinerFee = -not $Variables.ShowMinerFee
+ Write-Host "Toggled displaying " -NoNewline; Write-Host "M" -ForegroundColor Cyan -NoNewline; Write-Host "iner Fees to " -NoNewline; If ($Variables.ShowMinerFee) { Write-Host "on" -ForegroundColor Green -NoNewline } Else { Write-Host "off" -ForegroundColor Red -NoNewline }; Write-Host "."
+ $Variables.RefreshNeeded = $true
+ Start-Sleep -Seconds 2
+ }
+ "n" {
+ $Variables.ShowCoinName = -not $Variables.ShowCoinName
+ Write-Host "Toggled displaying Coin" -NoNewline; Write-Host "N" -ForegroundColor Cyan -NoNewline; Write-Host "ame to " -NoNewline; If ($Variables.ShowCoinName) { Write-Host "on" -ForegroundColor Green -NoNewline } Else { Write-Host "off" -ForegroundColor Red -NoNewline }; Write-Host "."
+ $Variables.RefreshNeeded = $true
+ Start-Sleep -Seconds 2
+ }
+ "p" {
+ $Variables.ShowPoolFee = -not $Variables.ShowPoolFee
+ Write-Host "Toggled displaying " -NoNewline; Write-Host "P" -ForegroundColor Cyan -NoNewline; Write-Host "ool Fees to " -NoNewline; If ($Variables.ShowPoolFee) { Write-Host "on" -ForegroundColor Green -NoNewline } Else { Write-Host "off" -ForegroundColor Red -NoNewline }; Write-Host "."
+ $Variables.RefreshNeeded = $true
+ Start-Sleep -Seconds 2
+ }
+ "r" {
+ If ($Variables.CalculatePowerCost) {
+ $Variables.ShowProfitBias = -not $Variables.ShowProfitBias
+ Write-Host "Toggled displaying P" -NoNewline; Write-Host "r" -ForegroundColor Cyan -NoNewline; Write-Host "ofit Bias to " -NoNewline; If ($Variables.ShowProfitBias) { Write-Host "on" -ForegroundColor Green -NoNewline } Else { Write-Host "off" -ForegroundColor Red -NoNewline }; Write-Host "."
+ $Variables.RefreshNeeded = $true
+ Start-Sleep -Seconds 2
+ }
+ }
+ "s" {
+ $Variables.UIStyle = If ($Variables.UIStyle -eq "Light") { "Full" } Else { "Light" }
+ Write-Host "UI " -NoNewline; Write-Host "S" -ForegroundColor Cyan -NoNewline; Write-Host "tyle set to " -NoNewline; Write-Host "$($Variables.UIStyle)" -ForegroundColor Blue -NoNewline; Write-Host " (Information about miners run in the past, failed miners & watchdog timers will " -NoNewline; If ($Variables.UIStyle -eq "Light") { Write-Host "not" -ForegroundColor Red -NoNewline; Write-Host " " -NoNewline }; Write-Host "be shown)."
+ $Variables.RefreshNeeded = $true
+ Start-Sleep -Seconds 2
+ }
+ "t" {
+ If ($Variables.CalculatePowerCost) {
+ $Variables.ShowProfit = -not $Variables.ShowProfit
+ Write-Host "Toggled displaying " -NoNewline; Write-Host "P" -ForegroundColor Cyan -NoNewline; Write-Host "rofit to " -NoNewline; If ($Variables.ShowProfit) { Write-Host "on" -ForegroundColor Green -NoNewline } Else { Write-Host "off" -ForegroundColor Red -NoNewline }; Write-Host "."
+ $Variables.RefreshNeeded = $true
+ Start-Sleep -Seconds 2
+ }
+ }
+ "u" {
+ If ($Variables.CalculatePowerCost) {
+ $Variables.ShowPowerUsage = -not $Variables.ShowPowerUsage
+ Write-Host "Toggled displaying power " -NoNewline; Write-Host "u" -ForegroundColor Cyan -NoNewline; Write-Host "sage to " -NoNewline; If ($Variables.ShowPowerUsage) { Write-Host "on" -ForegroundColor Green -NoNewline } Else { Write-Host "off" -ForegroundColor Red -NoNewline }; Write-Host "."
+ $Variables.RefreshNeeded = $true
+ Start-Sleep -Seconds 2
+ }
+ }
+ "y" {
+ $Variables.ShowCurrency = -not $Variables.ShowCurrency
+ Write-Host "Toggled displaying Currenc" -NoNewline; Write-Host "y" -ForegroundColor Cyan -NoNewline; Write-Host " to " -NoNewline; If ($Variables.ShowCurrency) { Write-Host "on" -ForegroundColor Green -NoNewline } Else { Write-Host "off" -ForegroundColor Red -NoNewline }; Write-Host "."
+ $Variables.RefreshNeeded = $true
+ Start-Sleep -Seconds 2
+ }
+ }
+ }
+ }
+
+ # Timer never disposes objects until it is disposed
+ $MainForm.Number += 1
+ $TimerUI.Stop()
+
+ TimerUITick
+ If ($MainForm.Number -gt 6000) {
+ $MainForm.Number = 0
+ $TimerUI.Remove_Tick({ TimerUITick })
+ $TimerUI.Dispose()
+ $TimerUI = New-Object System.Windows.Forms.Timer
+ $TimerUI.Add_Tick({ TimerUITick })
+ }
+ $TimerUI.Start()
+ }
+ )
+
+ $TimerUI.Interval = 50
+ $TimerUI.Stop()
+ $TimerUI.Enabled = $true
+}
+
+$MainForm = New-Object System.Windows.Forms.Form
+$MainForm.Icon = New-Object System.Drawing.Icon (".\Data\NM.ICO")
+$MainForm.MinimumSize = [System.Drawing.Size]::new(756, 501) # best to keep under 800x600
+$MainForm.Text = $Variables.Branding.ProductLabel
+$MainForm.TopMost = $false
+$MainForm.MaximizeBox = $true
+$MainForm | Add-Member -Name "Variables" -Value $Variables -MemberType NoteProperty -Force
+If ($Config.StartGUIMinimized) { $MainForm.WindowState = [System.Windows.Forms.FormWindowState]::Minimized }
+
+# Form Controls
+$MainFormControls = @()
+
+$Variables.StatusText = "Idle"
+$RunPage = New-Object System.Windows.Forms.TabPage
+$RunPage.Text = "Run"
+$EarningsPage = New-Object System.Windows.Forms.TabPage
+$EarningsPage.Text = "Earnings"
+$SwitchingPage = New-Object System.Windows.Forms.TabPage
+$SwitchingPage.Text = "Switching Log"
+$MonitoringPage = New-Object System.Windows.Forms.TabPage
+$MonitoringPage.Text = "Rig Monitoring"
+$BenchmarksPage = New-Object System.Windows.Forms.TabPage
+$BenchmarksPage.Text = "Benchmarks"
+
+$LabelCopyright = New-Object System.Windows.Forms.LinkLabel
+$LabelCopyright.Size = New-Object System.Drawing.Size(320, 16)
+$LabelCopyright.LinkColor = [System.Drawing.Color]::Blue
+$LabelCopyright.ActiveLinkColor = [System.Drawing.Color]::Blue
+$LabelCopyright.TextAlign = "MiddleRight"
+$LabelCopyright.Text = "Copyright (c) 2018-$((Get-Date).Year) Nemo, MrPlus && UselessGuru"
+$LabelCopyright.Add_Click({ Start-Process "https://github.com/Minerx117/NemosMiner/blob/master/LICENSE" })
+$MainFormControls += $LabelCopyright
+
+$TabControl = New-Object System.Windows.Forms.TabControl
+$TabControl.DataBindings.DefaultDataSourceUpdateMode = 0
+$TabControl.Location = [System.Drawing.Point]::new(10, 91)
+$TabControl.Name = "TabControl"
+$TabControl.Controls.AddRange(@($RunPage, $EarningsPage, $SwitchingPage, $MonitoringPage, $BenchmarksPage))
+
+$TabControl_SelectedIndexChanged = {
+ Update-TabControl
+}
+$TabControl.Add_SelectedIndexChanged($TabControl_SelectedIndexChanged)
+
+$MainForm.Controls.Add($TabControl)
+
+$PictureBoxLogo = New-Object Windows.Forms.PictureBox
+$PictureBoxLogo.Width = 47 #$img.Size.Width
+$PictureBoxLogo.Height = 47 #$img.Size.Height
+$PictureBoxLogo.SizeMode = 1
+$PictureBoxLogo.ImageLocation = $Variables.Branding.LogoPath
+$MainFormControls += $PictureBoxLogo
+
+$LabelEarningsDetails = New-Object System.Windows.Forms.TextBox
+$LabelEarningsDetails.Tag = ""
+$LabelEarningsDetails.MultiLine = $true
+$LabelEarningsDetails.Text = ""
+$LabelEarningsDetails.AutoSize = $false
+$LabelEarningsDetails.Height = 77
+$LabelEarningsDetails.Location = [System.Drawing.Point]::new(57, 2)
+$LabelEarningsDetails.Font = [System.Drawing.Font]::new("Lucida Console", 10)
+$LabelEarningsDetails.BorderStyle = 'None'
+$LabelEarningsDetails.BackColor = [System.Drawing.SystemColors]::Control
+$LabelEarningsDetails.ForeColor = [System.Drawing.Color]::Green
+$LabelEarningsDetails.Visible = $true
+$MainFormControls += $LabelEarningsDetails
+
+$LabelMiningStatus = New-Object System.Windows.Forms.Label
+$LabelMiningStatus.Text = ""
+$LabelMiningStatus.AutoSize = $false
+$LabelMiningStatus.Location = [System.Drawing.Point]::new(247, 2)
+$LabelMiningStatus.Width = 300
+$LabelMiningStatus.Height = 30
+$LabelMiningStatus.Font = [System.Drawing.Font]::new("Microsoft Sans Serif", 14)
+$LabelMiningStatus.TextAlign = "MiddleRight"
+$LabelMiningStatus.ForeColor = [System.Drawing.Color]::Green
+$LabelMiningStatus.BackColor = [System.Drawing.Color]::Transparent
+$MainFormControls += $LabelMiningStatus
+
+$ButtonStart = New-Object System.Windows.Forms.Button
+$ButtonStart.Text = "Start"
+$ButtonStart.Width = 60
+$ButtonStart.Height = 30
+$ButtonStart.Location = [System.Drawing.Point]::new(550, 50)
+$ButtonStart.Font = [System.Drawing.Font]::new("Microsoft Sans Serif", 10)
+$ButtonStart.Visible = $true
+$ButtonStart.Enabled = (-not $Config.Autostart)
+$MainFormControls += $ButtonStart
+
+$ButtonPause = New-Object System.Windows.Forms.Button
+$ButtonPause.Text = "Pause"
+$ButtonPause.Width = 60
+$ButtonPause.Height = 30
+$ButtonPause.Location = [System.Drawing.Point]::new(610, 50)
+$ButtonPause.Font = [System.Drawing.Font]::new("Microsoft Sans Serif", 10)
+$ButtonPause.Visible = $true
+$ButtonPause.Enabled = $Config.Autostart
+$MainFormControls += $ButtonPause
+
+$ButtonStop = New-Object System.Windows.Forms.Button
+$ButtonStop.Text = "Stop"
+$ButtonStop.Width = 60
+$ButtonStop.Height = 30
+$ButtonStop.Location = [System.Drawing.Point]::new(670, 50)
+$ButtonStop.Font = [System.Drawing.Font]::new("Microsoft Sans Serif", 10)
+$ButtonStop.Visible = $true
+$ButtonStop.Enabled = $Config.Autostart
+$MainFormControls += $ButtonStop
+
+$LabelNotifications = New-Object System.Windows.Forms.TextBox
+$LabelNotifications.Tag = ""
+$LabelNotifications.MultiLine = $true
+$LabelNotifications.Text = ""
+$LabelNotifications.AutoSize = $false
+$LabelNotifications.Width = 280
+$LabelNotifications.Height = 18
+$LabelNotifications.Location = [System.Drawing.Point]::new(10, 49)
+$LabelNotifications.Font = [System.Drawing.Font]::new("Microsoft Sans Serif", 10)
+$LabelNotifications.BorderStyle = 'None'
+$LabelNotifications.BackColor = [System.Drawing.SystemColors]::Control
+$LabelNotifications.Visible = $true
+$MainFormControls += $LabelNotifications
+
+# Run Page Controls
+$RunPageControls = @()
+
+$Variables.LabelStatus = New-Object System.Windows.Forms.TextBox
+$Variables.LabelStatus.MultiLine = $true
+$Variables.LabelStatus.Scrollbars = "Vertical"
+$Variables.LabelStatus.WordWrap = $true
+$Variables.LabelStatus.Text = ""
+$Variables.LabelStatus.AutoSize = $true
+$Variables.LabelStatus.Height = 202
+$Variables.LabelStatus.Location = [System.Drawing.Point]::new(2, 2)
+$Variables.LabelStatus.Font = [System.Drawing.Font]::new("Consolas", 10)
+
+$RunPageControls += $Variables.LabelStatus
+
+$LabelRunningMiners = New-Object System.Windows.Forms.Label
+$LabelRunningMiners.AutoSize = $false
+$LabelRunningMiners.Width = 450
+$LabelRunningMiners.Height = 16
+$LabelRunningMiners.Location = [System.Drawing.Point]::new(2, 213)
+$LabelRunningMiners.Font = [System.Drawing.Font]::new("Microsoft Sans Serif", 10)
+$RunPageControls += $LabelRunningMiners
+
+$RunningMinersDGV = New-Object System.Windows.Forms.DataGridView
+$RunningMinersDGV.Location = [System.Drawing.Point]::new(2, 232)
+$RunningMinersDGV.DataBindings.DefaultDataSourceUpdateMode = 0
+$RunningMinersDGV.AutoSizeColumnsMode = "Fill"
+$RunningMinersDGV.ColumnHeadersHeightSizeMode = "AutoSize"
+$RunningMinersDGV.RowHeadersVisible = $false
+$RunningMinersDGV.AllowUserToAddRows = $false
+$RunningMinersDGV.AllowUserToOrderColumns = $true
+$RunningMinersDGV.AllowUserToResizeColumns = $true
+$RunningMinersDGV.AllowUserToResizeRows = $false
+$RunningMinersDGV.ReadOnly = $true
+$RunningMinersDGV.EnableHeadersVisualStyles = $false
+$RunningMinersDGV.ColumnHeadersDefaultCellStyle.BackColor = [System.Drawing.SystemColors]::MenuBar
+$RunPageControls += $RunningMinersDGV
+
+# Earnings Page Controls
+$EarningsPageControls = @()
+
+$EarningsChart1 = New-Object System.Windows.Forms.DataVisualization.Charting.Chart
+$EarningsChart1.BackColor = [System.Drawing.Color]::FromArgb(255, 240, 240, 240) #"#F0F0F0"
+$EarningsPageControls += $EarningsChart1
+
+$EarningsChart2 = New-Object System.Windows.Forms.DataVisualization.Charting.Chart
+$EarningsChart2.BackColor = [System.Drawing.Color]::FromArgb(255, 240, 240, 240) #"#F0F0F0"
+$EarningsPageControls += $EarningsChart2
+
+$LabelEarnings = New-Object System.Windows.Forms.Label
+$LabelEarnings.AutoSize = $false
+$LabelEarnings.Width = 450
+$LabelEarnings.Height = 16
+$LabelEarnings.Location = [System.Drawing.Point]::new(2, 149)
+$LabelEarnings.Font = [System.Drawing.Font]::new("Microsoft Sans Serif", 10)
+$EarningsPageControls += $LabelEarnings
+
+$EarningsDGV = New-Object System.Windows.Forms.DataGridView
+$EarningsDGV.Location = [System.Drawing.Point]::new(2, 167)
+$EarningsDGV.DataBindings.DefaultDataSourceUpdateMode = 0
+$EarningsDGV.AutoSizeColumnsMode = "Fill"
+$EarningsDGV.ColumnHeadersHeightSizeMode = "AutoSize"
+$EarningsDGV.RowHeadersVisible = $false
+$EarningsDGV.AllowUserToAddRows = $false
+$EarningsDGV.AllowUserToOrderColumns = $true
+$EarningsDGV.AllowUserToResizeColumns = $true
+$EarningsDGV.AllowUserToResizeRows = $false
+$EarningsDGV.ReadOnly = $true
+$EarningsDGV.EnableHeadersVisualStyles = $false
+$EarningsDGV.ColumnHeadersDefaultCellStyle.BackColor = [System.Drawing.SystemColors]::MenuBar
+$EarningsPageControls += $EarningsDGV
+
+# Switching Page Controls
+$SwitchingPageControls = @()
+
+$CheckShowSwitchingCPU = New-Object System.Windows.Forms.CheckBox
+$CheckShowSwitchingCPU.Tag = "CPU"
+$CheckShowSwitchingCPU.Text = "CPU"
+$CheckShowSwitchingCPU.AutoSize = $false
+$CheckShowSwitchingCPU.Width = 60
+$CheckShowSwitchingCPU.Height = 20
+$CheckShowSwitchingCPU.Location = [System.Drawing.Point]::new(2, 2)
+$CheckShowSwitchingCPU.Font = [System.Drawing.Font]::new("Microsoft Sans Serif", 10)
+$SwitchingPageControls += $CheckShowSwitchingCPU
+$CheckShowSwitchingCPU | ForEach-Object { $_.Add_Click({ CheckBoxSwitching_Click($this) }) }
+
+$CheckShowSwitchingNVIDIA = New-Object System.Windows.Forms.CheckBox
+$CheckShowSwitchingNVIDIA.Tag = "NVIDIA"
+$CheckShowSwitchingNVIDIA.Text = "NVIDIA"
+$CheckShowSwitchingNVIDIA.AutoSize = $false
+$CheckShowSwitchingNVIDIA.Width = 70
+$CheckShowSwitchingNVIDIA.Height = 20
+$CheckShowSwitchingNVIDIA.Location = [System.Drawing.Point]::new(62, 2)
+$CheckShowSwitchingNVIDIA.Font = [System.Drawing.Font]::new("Microsoft Sans Serif", 10)
+$SwitchingPageControls += $CheckShowSwitchingNVIDIA
+$CheckShowSwitchingNVIDIA | ForEach-Object { $_.Add_Click({ CheckBoxSwitching_Click($this) }) }
+
+$CheckShowSwitchingAMD = New-Object System.Windows.Forms.CheckBox
+$CheckShowSwitchingAMD.Tag = "AMD"
+$CheckShowSwitchingAMD.Text = "AMD"
+$CheckShowSwitchingAMD.AutoSize = $false
+$CheckShowSwitchingAMD.Width = 100
+$CheckShowSwitchingAMD.Height = 20
+$CheckShowSwitchingAMD.Location = [System.Drawing.Point]::new(137, 2)
+$CheckShowSwitchingAMD.Font = [System.Drawing.Font]::new("Microsoft Sans Serif", 10)
+$SwitchingPageControls += $CheckShowSwitchingAMD
+$CheckShowSwitchingAMD | ForEach-Object { $_.Add_Click({ CheckBoxSwitching_Click($this) }) }
+
+Function CheckBoxSwitching_Click {
+ If (-not ($this.Text -or $SwitchingDGV.DataSource)) {
+ $CheckShowSwitchingAMD.Checked = ($Variables.Devices | Where-Object { $_.State -eq [DeviceState]::Enabled } | Where-Object Type -EQ "GPU" | Where-Object Vendor -EQ "AMD")
+ $CheckShowSwitchingCPU.Checked = ($Variables.Devices | Where-Object { $_.State -eq [DeviceState]::Enabled } | Where-Object Name -Like "CPU#*")
+ $CheckShowSwitchingNVIDIA.Checked = ($Variables.Devices | Where-Object { $_.State -eq [DeviceState]::Enabled } | Where-Object Type -EQ "GPU" | Where-Object Vendor -EQ "NVIDIA")
+ }
+
+ $SwitchingDisplayTypes = @()
+ $SwitchingPageControls | ForEach-Object { If ($_.Checked) { $SwitchingDisplayTypes += $_.Tag } }
+ If (Test-Path -Path ".\Logs\SwitchingLog.csv" -PathType Leaf) {
+ $SwitchingDGV.DataSource = Get-Content ".\Logs\SwitchingLog.csv" | ConvertFrom-Csv | Where-Object { $_.Type -in $SwitchingDisplayTypes } | Select-Object -Last 1000 | ForEach-Object { $_.Datetime = (Get-Date $_.DateTime).ToString("G"); $_ } | Select-Object @("DateTime", "Action", "Name", "Pool", "Algorithm", "Account", "Duration", "Device", "Type") | Out-DataTable
+ If ($SwitchingDGV.Columns) {
+ $SwitchingDGV.Columns[0].FillWeight = 80
+ $SwitchingDGV.Columns[1].FillWeight = 50
+ $SwitchingDGV.Columns[2].FillWeight = 150
+ $SwitchingDGV.Columns[3].FillWeight = 90
+ $SwitchingDGV.Columns[4].FillWeight = 65
+ $SwitchingDGV.Columns[5].FillWeight = 80
+ }
+ If ($SwitchingDGV.Columns[8]) {
+ $SwitchingDGV.Columns[0].HeaderText = "Date & Time"
+ $SwitchingDGV.Columns[6].HeaderText = "Running Time"
+ $SwitchingDGV.Columns[6].FillWeight = 50
+ $SwitchingDGV.Columns[7].FillWeight = 55
+ $SwitchingDGV.Columns[8].FillWeight = 50
+ }
+ $SwitchingDGV.ClearSelection()
+ }
+ Remove-Variable SwitchingDisplayTypes
+}
+
+$SwitchingDGV = New-Object System.Windows.Forms.DataGridView
+$SwitchingDGV.Location = [System.Drawing.Point]::new(2, 22)
+$SwitchingDGV.DataBindings.DefaultDataSourceUpdateMode = 0
+$SwitchingDGV.AutoSizeColumnsMode = "Fill"
+$SwitchingDGV.RowHeadersVisible = $false
+$SwitchingDGV.ColumnHeadersVisible = $true
+$SwitchingDGV.AllowUserToAddRows = $false
+$SwitchingDGV.AllowUserToOrderColumns = $true
+$SwitchingDGV.AllowUserToResizeColumns = $true
+$SwitchingDGV.AllowUserToResizeRows = $false
+$SwitchingDGV.ReadOnly = $true
+$SwitchingDGV.EnableHeadersVisualStyles = $false
+$SwitchingDGV.ColumnHeadersDefaultCellStyle.BackColor = [System.Drawing.SystemColors]::MenuBar
+$SwitchingPageControls += $SwitchingDGV
+
+# Estimations Page Controls
+$BenchmarkingPageControls = @()
+
+$LabelBenchmarks = New-Object System.Windows.Forms.Label
+$LabelBenchmarks.AutoSize = $false
+$LabelBenchmarks.Width = 450
+$LabelBenchmarks.Height = 18
+$LabelBenchmarks.Location = [System.Drawing.Point]::new(2, 4)
+$LabelBenchmarks.Font = [System.Drawing.Font]::new("Microsoft Sans Serif", 10)
+$BenchmarkingPageControls += $LabelBenchmarks
+
+$BenchmarksDGV = New-Object System.Windows.Forms.DataGridView
+$BenchmarksDGV.Location = [System.Drawing.Point]::new(2, 22)
+$BenchmarksDGV.DataBindings.DefaultDataSourceUpdateMode = 0
+$BenchmarksDGV.AutoSizeColumnsMode = "Fill"
+$BenchmarksDGV.ColumnHeadersHeightSizeMode = "AutoSize"
+$BenchmarksDGV.RowHeadersVisible = $false
+$BenchmarksDGV.ColumnHeadersVisible = $true
+$BenchmarksDGV.AllowUserToAddRows = $false
+$BenchmarksDGV.AllowUserToOrderColumns = $true
+$BenchmarksDGV.AllowUserToResizeColumns = $true
+$BenchmarksDGV.AllowUserToResizeRows = $false
+$BenchmarksDGV.ReadOnly = $true
+$BenchmarksDGV.EnableHeadersVisualStyles = $false
+$BenchmarksDGV.ColumnHeadersDefaultCellStyle.BackColor = [System.Drawing.SystemColors]::MenuBar
+$BenchmarkingPageControls += $BenchmarksDGV
+
+# Monitoring Page Controls
+$MonitoringPageControls = @()
+
+$LabelWorkers = New-Object System.Windows.Forms.Label
+$LabelWorkers.AutoSize = $false
+$LabelWorkers.Width = 450
+$LabelWorkers.Height = 18
+$LabelWorkers.Location = [System.Drawing.Point]::new(2, 4)
+$LabelWorkers.Font = [System.Drawing.Font]::new("Microsoft Sans Serif", 10)
+$MonitoringPageControls += $LabelWorkers
+
+$WorkersDGV = New-Object System.Windows.Forms.DataGridView
+$WorkersDGV.Location = [System.Drawing.Point]::new(2, 22)
+$WorkersDGV.DataBindings.DefaultDataSourceUpdateMode = 0
+$WorkersDGV.AutoSizeColumnsMode = "Fill"
+$WorkersDGV.ColumnHeadersHeightSizeMode = "AutoSize"
+$WorkersDGV.AutoSizeRowsMode = "AllCells"
+$WorkersDGV.DefaultCellStyle= @{ WrapMode = "True" }
+$WorkersDGV.RowHeadersVisible = $false
+$WorkersDGV.AllowUserToAddRows = $false
+$WorkersDGV.ColumnHeadersVisible = $true
+$WorkersDGV.AllowUserToOrderColumns = $true
+$WorkersDGV.AllowUserToResizeColumns = $true
+$WorkersDGV.AllowUserToResizeRows = $true
+$WorkersDGV.ReadOnly = $true
+$WorkersDGV.EnableHeadersVisualStyles = $false
+$WorkersDGV.ColumnHeadersDefaultCellStyle.BackColor = [System.Drawing.SystemColors]::MenuBar
+$MonitoringPageControls += $WorkersDGV
+
+$ConfigMonitoring = New-Object System.Windows.Forms.LinkLabel
+$ConfigMonitoring.Location = New-Object System.Drawing.Size(2, 304)
+$ConfigMonitoring.Size = New-Object System.Drawing.Size(500, 20)
+$ConfigMonitoring.Font = [System.Drawing.Font]::new("Microsoft Sans Serif", 10)
+$ConfigMonitoring.TextAlign = "MiddleLeft"
+$ConfigMonitoring.Add_Click({ If ($Variables.APIRunspace) { Start-Process "http://localhost:$($Variables.APIRunspace.APIPort)/rigmonitor.html" } })
+$MonitoringPageControls += $ConfigMonitoring
+
+$MainForm | Add-Member -Name Number -Value 0 -MemberType NoteProperty
+
+$TimerUI = New-Object System.Windows.Forms.Timer
+$TimerUI.Enabled = $false
+
+$ButtonPause.Add_Click(
+ {
+ If ($Variables.NewMiningStatus -ne "Paused") {
+ $Variables.NewMiningStatus = "Paused"
+ $Variables.RestartCycle = $true
+ }
+ }
+)
+
+$ButtonStop.Add_Click(
+ {
+ If ($Variables.NewMiningStatus -ne "Idle") {
+ $Variables.NewMiningStatus = "Idle"
+ $Variables.RestartCycle = $true
+ }
+ }
+)
+
+$ButtonStart.Add_Click(
+ {
+ If ($Variables.NewMiningStatus -ne "Running" -or $Variables.IdleRunspace -eq "Idle") {
+ $Variables.NewMiningStatus = "Running"
+ $Variables.RestartCycle = $true
+ }
+ }
+)
+
+$MainForm.Controls.AddRange(@($MainFormControls))
+$RunPage.Controls.AddRange(@($RunPageControls))
+$EarningsPage.Controls.AddRange(@($EarningsPageControls))
+$SwitchingPage.Controls.AddRange(@($SwitchingPageControls))
+$BenchmarksPage.Controls.AddRange(@($BenchmarkingPageControls))
+$MonitoringPage.Controls.AddRange(@($MonitoringPageControls))
+
+Function MainForm_Resize {
+
+ $TabControl.Width = $MainForm.Width - 33
+ $TabControl.Height = $MainForm.Height - 139
+
+ $LabelEarningsDetails.Width = $MainForm.Width - 270
+ $LabelMiningStatus.Location = [System.Drawing.Point]::new(($MainForm.Width - $LabelMiningStatus.Width - 22), 2)
+ $LabelMiningStatus.BringToFront()
+
+ $LabelCopyright.Location = [System.Drawing.Point]::new(($MainForm.Width - $LabelCopyright.Width - 22), 95)
+ $LabelCopyright.BringToFront()
+
+ $ButtonStart.Location = [System.Drawing.Point]::new($MainForm.Width - 205, 62)
+ $ButtonPause.Location = [System.Drawing.Point]::new($MainForm.Width - 145, 62)
+ $ButtonStop.Location = [System.Drawing.Point]::new($MainForm.Width - 85, 62)
+
+ $Variables.LabelStatus.Width = $TabControl.Width - 13
+ $Variables.LabelStatus.Height = ($TabControl.Height - 20) * 0.6
+
+ $LabelRunningMiners.Location = [System.Drawing.Point]::new(2, ($Variables.LabelStatus.Height + 7))
+
+ $RunningMinersDGV.Location = [System.Drawing.Point]::new(2, ($Variables.LabelStatus.Height + 25))
+ $RunningMinersDGV.Width = $TabControl.Width - 13
+ $RunningMinersDGV.Height = ($TabControl.Height - $Variables.LabelStatus.Height - 56)
+
+ $WorkersDGV.Height = $TabControl.Height - 73
+ $ConfigMonitoring.Location = [System.Drawing.Point]::new(2, ($RunningMinersDGV.Bottom - 18))
+
+ If ($MainForm.Width -gt 722) {
+ $EarningsChart1.Width = ($TabControl.Width - 14) * 0.75
+ $EarningsChart2.Left = $EarningsChart1.Width + 20
+ $EarningsChart2.Width = ($TabControl.Width - $EarningsChart1.Width - 50)
+ $EarningsChart1.Height = $EarningsChart2.Height = ($TabControl.Height - 60) * 0.4
+ $LabelEarnings.Location = [System.Drawing.Point]::new(2, ($EarningsChart1.Height + 4))
+ }
+
+ $EarningsDGV.Location = [System.Drawing.Point]::new(2, ($EarningsChart1.Height + 22))
+
+ $BenchmarksDGV.Width = $EarningsDGV.Width = $SwitchingDGV.Width = $WorkersDGV.Width = $TabControl.Width - 14
+ $BenchmarksDGV.Height = $EarningsDGV.Height = $SwitchingDGV.Height = $TabControl.Height - 53
+}
+
+$MainForm.Add_Load(
+ {
+ If (Test-Path ".\Config\WindowSettings.json" -PathType Leaf) {
+ $WindowSettings = Get-Content -Path ".\Config\WindowSettings.json" -ErrorAction Ignore | ConvertFrom-Json -AsHashtable -ErrorAction Ignore
+ If ($WindowSettings.Height -ge $MainForm.MinimumSize.Height -and $WindowSettings.Width -ge $MainForm.MinimumSize.Width) {
+ # Restore window size
+ $MainForm.Height = $WindowSettings.Height
+ $MainForm.Width = $WindowSettings.Width
+ $MainForm.Top = $WindowSettings.Top
+ $MainForm.Left = $WindowSettings.Left
+ }
+ }
+ Update-TabControl
+ MainForm_Load
+ }
+)
+
+$MainForm.Add_Shown(
+ {
+ # TimerCheckVersion
+ $TimerCheckVersion = New-Object System.Windows.Forms.Timer
+ $TimerCheckVersion.Enabled = $true
+ $TimerCheckVersion.Interval = 1 <#timer resolution 1 ms#> * 1000 <#milliseconds#> * 60 <#seconds#> * 60 <#minutes#> * 24 <#hours#>
+ $TimerCheckVersion.Add_Tick(
+ {
+ Get-NMVersion
+ }
+ )
+ }
+)
+
+$MainForm.Add_FormClosing(
+ {
+ Write-Message -Level Info "Shutting down $($Variables.Branding.ProductLabel)..."
+ $Variables.NewMiningStatus = "Idle"
+ $TimerUI.Stop()
+
+ Stop-Mining
+ Stop-IdleDetection
+ Stop-BrainJob
+ Stop-BalancesTracker
+
+ # Save window settings
+ $MainForm.DesktopBounds | ConvertTo-Json -ErrorAction Ignore | Out-File -FilePath ".\Config\WindowSettings.json" -Force -Encoding utf8NoBOM -ErrorAction SilentlyContinue
+
+ Write-Message -Level Info "$($Variables.Branding.ProductLabel) has shut down."
+
+ Stop-Process -Id $PID
+ }
+)
+
+$MainForm.Add_SizeChanged(
+ {
+ MainForm_Resize
+ }
+)
+
+[Void]$MainForm.ShowDialog()
diff --git a/OptionalMiners/bminerf.ps1 b/OptionalMiners/bminerf.ps1
deleted file mode 100644
index 91fb0a953f..0000000000
--- a/OptionalMiners/bminerf.ps1
+++ /dev/null
@@ -1,41 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-Bminerf1553\bminer.exe"
-$Uri = "https://www.bminercontent.com/releases/bminer-lite-v15.5.3-747d98e-amd64.zip"
-$Commands = [PSCustomObject]@{
- #"equihashBTG" = " -uri zhash://" #EquihashBTG
- #"equihash144" = " -pers auto -uri equihash1445://" #Equihash144
- #"zhash" = " -pers auto -uri equihash1445://" #Zhash
- #"ethash" = " -uri ethstratum://" #Ethash
- #"cuckoocycle" = " -uri aeternity://" #aeternity
- #"beam" = " -uri beam://" #beam
- #"grincuckaroo29" = " -uri cuckaroo29://" #grincuckaroo29
- #"grincuckatoo31" = " -uri cuckatoo31://" #grincuckatoo31 (8gb cards work win7,8, 8.1 & Linux. Win10 requires 10gb+vram)
-
-}
-$Port = $Variables.NVIDIAMinerAPITCPPort
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- switch ($_) {
- "ethash" {$Fee = 0.0065} # substract devfee
- "grincuckaroo29" {$Fee = 0.01} # substract devfee
- "grincuckatoo31" {$Fee = 0.01} # substract devfee
- default {$Fee = 0.02} # substract devfee
- }
- $Pass = If ($Pools.($Algo).Pass -like "*,*") {$Pools.($Algo).Pass.ToString().replace(',','%2C')} else {$Pools.($Algo).Pass}
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "$($Commands.$_)$($Pools.($Algo).User):$($Pass)@$($Pools.($Algo).Host):$($Pools.($Algo).Port) -max-temperature 94 -devices $($Config.SelGPUCC) -api 127.0.0.1:$Port"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * (1 - $Fee)} # substract devfee
- API = "bminer"
- Port = $Port
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/OptionalMiners/cryptodredge.ps1 b/OptionalMiners/cryptodredge.ps1
deleted file mode 100644
index d6ccf7fe16..0000000000
--- a/OptionalMiners/cryptodredge.ps1
+++ /dev/null
@@ -1,61 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) { . .\Include.ps1; RegisterLoaded(".\Include.ps1") }
-
-$Path = ".\Bin\NVIDIA-CryptoDredge0191\CryptoDredge.exe"
-$Uri = "https://github.com/technobyl/CryptoDredge/releases/download/v0.19.1/CryptoDredge_0.19.1_cuda_10.1_windows.zip"
-
-$Commands = [PSCustomObject]@{
- "argon2d250" = " --intensity 8 -a argon2d250" #argon2d250
- "argon2d4096" = " --intensity 8 -a argon2d4096" #argon2d4096
- #"argon2d-uis" = " --intensity 8 -a argon2d4096" #argon2d4096
- "argon2ddyn" = " --intensity 6 -a argon2d-dyn" #Argon2d-dyn
- "allium" = " --intensity 8 -a allium" #Allium
- #"lyra2v3" = " --intensity 8 -a lyra2v3" #Lyra2v3
- #"lyra2REv3" = " --intensity 8 -a lyra2v3" #lyra2REv3
- "lyra2zz " = " --intensity 8 -a lyra2zz" #Lyra2zz
- "neoscrypt" = " --intensity 6 -a neoscrypt"
- "phi2" = " --intensity 8 -a phi2" #Phi2
- "lyra2vc0ban" = " --intensity 8 -a lyra2vc0ban" #Lyra2vc0banHash
- #"cryptonightheavy" = " --intensity 8 -a cryptonightheavy" # CryptoNightHeavy
- #"x22i" = " --intensity 8 -a x22i" # X22i
- #"tribus" = " --intensity 8 -a tribus" #Tribus
- #"cnv8" = " --intensity 8 -a cnv8" #CryptoNightv8
- #"c11" = " --intensity 8 -a c11" #C11
- "skunk" = " --intensity 8 -a skunk" #Skunk
- #"mtp" = " --intensity 8 -a mtp" #Mtp
- #"bcd" = " --intensity 8 -a bcd" #Bcd
- #"x16rt" = " --intensity 8 -a x16rt" #X16rt
- #"x21s" = " --intensity 8 -a x21s" #X21s
- #"x16s" = " --intensity 8 -a x16s" #X16s
- #"x17" = " --intensity 8 -a x17" #X17
- #"bitcore" = " --intensity 8 -a bitcore" #Bitcore
- "hmq1725" = " --intensity 8 -a hmq1725" #Hmq1725
- #"dedal" = " --intensity 8 -a dedal" #Dedal
- "pipe" = " --intensity 8 -a pipe" #Pipe
- #"x16r" = " --intensity 8 -a x16r" #x16r
- #"grincuckaroo29" = " --intensity 8 -a cuckaroo29" #Grincuckaroo29
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- If ($Algo -eq "phi2" -and $Pools.($Algo).Host -like "*zergpool*") { return }
- switch ($_) {
- "mtp" { $Fee = 0.02 } # substract devfee
- default { $Fee = 0.01 } # substract devfee
- }
-
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--timeout 60 --api-type ccminer-tcp --cpu-priority 4 --no-watchdog -r -1 -R 1 -b 127.0.0.1:$($Variables.NVIDIAMinerAPITCPPort) -d $($Config.SelGPUCC) -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * (1 - $Fee) } # substract devfee
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/OptionalMiners/cryptodredge16.ps1 b/OptionalMiners/cryptodredge16.ps1
deleted file mode 100644
index 28adaa0d23..0000000000
--- a/OptionalMiners/cryptodredge16.ps1
+++ /dev/null
@@ -1,29 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-CryptoDredge0160\CryptoDredge.exe"
-$Uri = "https://github.com/technobyl/CryptoDredge/releases/download/v0.16.0/CryptoDredge_0.16.0_cuda_10.0_windows.zip"
-
-$Commands = [PSCustomObject]@{
- "exosis" = " --intensity 8 -a exosis" #Exosis
- "phi" = " --intensity 8 -a phi" #Phi
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
-
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--timeout 60 --api-type ccminer-tcp --cpu-priority 4 --no-watchdog -r -1 -R 1 -b 127.0.0.1:$($Variables.NVIDIAMinerAPITCPPort) -d $($Config.SelGPUCC) -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * .99} # substract 1% devfee
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/OptionalMiners/cryptodredgephi2.ps1 b/OptionalMiners/cryptodredgephi2.ps1
deleted file mode 100644
index 0d908f065c..0000000000
--- a/OptionalMiners/cryptodredgephi2.ps1
+++ /dev/null
@@ -1,33 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) { . .\Include.ps1; RegisterLoaded(".\Include.ps1") }
-
-$Path = ".\Bin\NVIDIA-CryptoDredge0191phi2\CryptoDredge.exe"
-$Uri = "https://github.com/technobyl/CryptoDredge/releases/download/v0.19.1/CryptoDredge_0.19.1_cuda_10.1_windows.zip"
-
-$Commands = [PSCustomObject]@{
- "phi2" = ",mc=SPDR/AGM --intensity 8 -a phi2" #Phi2
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- If ($Algo -eq "phi2" -and $Pools.($Algo).Host -notlike "*zergpool*") { return } #temp fix for LUX zergpool
- switch ($_) {
- "mtp" { $Fee = 0.02 } # substract devfee
- default { $Fee = 0.01 } # substract devfee
- }
-
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--timeout 60 --api-type ccminer-tcp --cpu-priority 4 --no-watchdog -r -1 -R 1 -b 127.0.0.1:$($Variables.NVIDIAMinerAPITCPPort) -d $($Config.SelGPUCC) -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * (1 - $Fee) } # substract devfee
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/OptionalMiners/ethashclaymore.ps1 b/OptionalMiners/ethashclaymore.ps1
deleted file mode 100644
index 16aa0a1f09..0000000000
--- a/OptionalMiners/ethashclaymore.ps1
+++ /dev/null
@@ -1,27 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\Ethash-Claymore143b\EthDcrMiner64.exe"
-$Uri = "https://github.com/nemosminer/Claymores-Dual-Ethereum/releases/download/v14.3/ClaymoresDualEthereumv143.7z"
-
-$Commands = [PSCustomObject]@{
- "ethash" = " -di $($($Config.SelGPUCC).Replace(',',''))" #Ethash -strap 1 -strap 2 -strap 3 -strap 4 -strap 5 -strap 6
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "-wd 0 -esm 3 -allpools 1 -allcoins 1 -platform 2 -mode 1 -mport -$($Variables.NVIDIAMinerAPITCPPort) -epool $($Pools.($Algo).Host):$($Pools.($Algo).Port) -ewal $($Pools.($Algo).User) -epsw $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Week * .99} # substract 1% devfee
- API = "ethminer"
- Port = $Variables.NVIDIAMinerAPITCPPort #3333
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/OptionalMiners/ethashphoenix.ps1 b/OptionalMiners/ethashphoenix.ps1
deleted file mode 100644
index 71538dc640..0000000000
--- a/OptionalMiners/ethashphoenix.ps1
+++ /dev/null
@@ -1,25 +0,0 @@
-
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\Ethash-Phoenix42c\PhoenixMiner.exe"
-$Uri = "https://nemosminer.com/data/optional/PhoenixMiner_4.2c_Windows.7z"
-$Commands = [PSCustomObject]@{
- "ethash" = " -di $($($Config.SelGPUCC).Replace(',',''))" #Ethash fastest and Epoch 267 ready
-}
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
-$Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "-nvdo 1 -esm 3 -allpools 1 -allcoins 1 -platform 2 -mport -$($Variables.NVIDIAMinerAPITCPPort) -epool $($Pools.Ethash.Host):$($Pools.Ethash.Port) -ewal $($Pools.Ethash.User) -epsw $($Pools.Ethash.Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * .9935} # substract 0.65% devfee
- API = "ethminer"
- Port = $Variables.NVIDIAMinerAPITCPPort #3333
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/OptionalMiners/gminer.ps1 b/OptionalMiners/gminer.ps1
deleted file mode 100644
index 118853294a..0000000000
--- a/OptionalMiners/gminer.ps1
+++ /dev/null
@@ -1,35 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-Gminer142\miner.exe"
-$Uri = "https://github.com/develsoftware/GMinerRelease/releases/download/1.42/gminer_1_42_windows64.zip"
-$Commands = [PSCustomObject]@{
- "equihash144" = " --devices $($Config.SelGPUDSTM) --algo 144_5 --pers auto" #Equihash144
- "zhash" = " --devices $($Config.SelGPUDSTM) --algo 144_5 --pers auto" #Zhash
- "equihash192" = " --devices $($Config.SelGPUDSTM) --algo 192_7 --pers auto" #Equihash192
- "equihash-btg" = " --devices $($Config.SelGPUDSTM) --algo 144_5 --pers BgoldPoW " # Equihash-btg MPH
- "equihash96" = " --devices $($Config.SelGPUDSTM) --algo 96_5 --pers auto" #Equihash96
- "beam" = " --devices $($Config.SelGPUDSTM) --algo 150_5 --pers auto" #Equihash150
- "grincuckaroo29" = " --devices $($Config.SelGPUDSTM) --algo grin29 --pers auto" #Grincuckaroo29
- #"cuckoocycle" = " --devices $($Config.SelGPUDSTM) --algo aeternity --pers auto" #Aeternity
- #"grincuckatoo31" = " --devices $($Config.SelGPUDSTM) --algo grin31 --pers auto" #Grincuckatoo31 (8gb cards work win7,8, 8.1 & Linux. Win10 requires 10gb+vram)
-
-}
-$Port = $Variables.NVIDIAMinerAPITCPPort
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--intensity 100 --watchdog 0 --api $($Variables.NVIDIAMinerAPITCPPort) --server $($Pools.($Algo).Host) --port $($Pools.($Algo).Port) --user $($Pools.($Algo).User) --pass $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * .98} # substract 2% devfee
- API = "gminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/OptionalMiners/lolminer.ps1 b/OptionalMiners/lolminer.ps1
deleted file mode 100644
index 7dfec3e0a2..0000000000
--- a/OptionalMiners/lolminer.ps1
+++ /dev/null
@@ -1,33 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-AMD-lolMiner081\lolMiner.exe"
-$Uri = "https://github.com/Lolliedieb/lolMiner-releases/releases/download/0.8.1/lolMiner_v081_Win64.zip"
-
-$Commands = [PSCustomObject]@{
- #"equihash96" = " --coin MNX" #Equihash 96,5
- #"equihash144" = " --coin AUTO144_5" #Equihash 144,5
- #"equihash192" = " --coin AUTO192_7" #Equihash 192,7
- #"beam" = " --coin BEAM" #Equihash 150,5
- "grincuckatoo31" = " --coin GRIN-AT31" #grincuckatoo31
- }
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
-
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--user $($Pools.($Algo).User) --pool $($Pools.($Algo).Host) --port $($Pools.($Algo).Port) --devices $($Config.SelGPUCC) --apiport $($Variables.NVIDIAMinerAPITCPPort) --tls 0 --digits 2 --longstats 60 --shortstats 5 --connectattempts 3 --pass $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * .99} # substract 1% devfee
- API = "LOL"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
-
-
diff --git a/OptionalMiners/miniz.ps1 b/OptionalMiners/miniz.ps1
deleted file mode 100644
index bb56c0f689..0000000000
--- a/OptionalMiners/miniz.ps1
+++ /dev/null
@@ -1,30 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-miniZ13n5t\miniZ.exe"
-$Uri = "https://nemosminer.com/data/optional/miniZ_v1.3n5_cuda10_win-x64.7z"
-$Commands = [PSCustomObject]@{
- "equihash144" = " --algo 144,5 --pers auto" #Equihash144
- "zhash" = " --algo 144,5 --pers auto" #Zhash
- "equihash192" = " --algo 192,7 --pers auto" #Equihash192
- "equihash-btg" = " --algo 144,5 --pers BgoldPoW " # Equihash-btg MPH
- "equihash96" = " --algo 96,5 --pers auto" #Equihash96
- "beam" = " --algo 150,5 --pers auto" #Beam
-}
-$Port = $Variables.NVIDIAMinerAPITCPPort
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
-$Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--templimit 95 --intensity 100 --latency --nocolor --tempunits C -cd $($Config.SelGPUDSTM) --telemetry $($Variables.NVIDIAMinerAPITCPPort) --url $($Pools.($Algo).User)@$($Pools.($Algo).Host):$($Pools.($Algo).Port) --pass $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * .98} # substract 2% devfee
- API = "miniZ"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/OptionalMiners/multiminer.ps1 b/OptionalMiners/multiminer.ps1
deleted file mode 100644
index b3eb3408aa..0000000000
--- a/OptionalMiners/multiminer.ps1
+++ /dev/null
@@ -1,31 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-MultiMiner\multiminer.exe"
-$Uri = "https://github.com/bogdanadnan/multiminer/releases/download/v1.1.0/multiminer_v1.1.0_24.01.2019.zip"
-
-$Commands = [PSCustomObject]@{
- "argon2d4096" = " -a argon2d4096 --use-gpu=CUDA --gpu-batchsize=512 -t 2" #Argon2d4096 ( --gpu-id=$($Config.SelGPUCC) )
- #"argon2d-uis" = " -a argon2d4096 --use-gpu=CUDA --gpu-batchsize=512 -t 2" #Argon2d4096
- "argon2d250" = " -a argon2d250 --use-gpu CUDA -t 4 --gpu-batchsize 2048" #Argon2d4096
-
-}
-
-$Name = Get-Item $MyInvocation.MyCommand.Path | Select-Object -ExpandProperty BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name | ForEach {
-
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--max-temp=95 -R 1 -q -b $($Variables.NVIDIAMinerAPITCPPort) -o $($Pools.($Algo).Protocol)://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * .99} # substract 1% devfee
- API = "Ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/OptionalMiners/nanominer.ps1 b/OptionalMiners/nanominer.ps1
deleted file mode 100644
index 1f59f319e6..0000000000
--- a/OptionalMiners/nanominer.ps1
+++ /dev/null
@@ -1,27 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) { . .\Include.ps1; RegisterLoaded(".\Include.ps1") }
-
-$Path = ".\Bin\NVIDIA-nanominer130\cmdline_launcher.bat"
-$Uri = "https://github.com/nanopool/nanominer/releases/download/v1.3.0/nanominer-windows-1.3.0.zip"
-
-$Commands = [PSCustomObject]@{
- "cryptonightr" = "" #cryptonight/r (NiceHash)
- "cryptonight-monero" = "" #monero (Mining Pool Hub)
-}
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "-mport -$($Variables.NVIDIAMinerAPITCPPort) -algo cryptonightr -wallet $($Pools.($Algo).User) -rigName $($Pools.($Algo).Pass) -pool1 $($Pools.($Algo).Host):$($Pools.($Algo).Port)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * .99 } # substract 1% devfee
- API = "nanominer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/OptionalMiners/nbminer.ps1 b/OptionalMiners/nbminer.ps1
deleted file mode 100644
index f19a558329..0000000000
--- a/OptionalMiners/nbminer.ps1
+++ /dev/null
@@ -1,35 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-nbminer2321\nbminer.exe"
-$Uri = "https://nemosminer.com/data/optional/NBMiner_Win23.2.1.7z"
-
-$Commands = [PSCustomObject]@{
- #"grincuckatoo31" = " -a cuckatoo -o stratum+tcp://" #grincuckatoo31 (8gb cards work win7,8, 8.1 & Linux. Win10 requires 10gb+vram)
- "grincuckaroo29" = " -a cuckaroo -o stratum+tcp://" #grincuckaroo29
- "cuckoocycle" = " -a cuckoo_ae -o stratum+tcp://" #grincuckaroo29
- #"ethash" = " -a ethash -o ethnh+tcp://" #ethash
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- switch ($_) {
- "ethash" {$Fee = 0.0065}
- default {$Fee = 0.02}
- }
- If ($Pools.($Algo).Host -notlike "*nicehash*") {return}
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "$($Commands.$_)$($Pools.($Algo).Host):$($Pools.($Algo).Port) --cuckoo-intensity 0 --api 127.0.0.1:$($Variables.NVIDIAMinerAPITCPPort) -d $($Config.SelGPUCC) -u $($Pools.($Algo).User):$($Pools.($Algo).Pass)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * (1 - $Fee)} # substract devfee
- API = "NBMiner"
- Port = $Variables.NVIDIAMinerAPITCPPort #4068
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/OptionalMiners/trex.ps1 b/OptionalMiners/trex.ps1
deleted file mode 100644
index c2c9631045..0000000000
--- a/OptionalMiners/trex.ps1
+++ /dev/null
@@ -1,53 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-trex102\t-rex.exe"
-$Uri = "https://github.com/trexminer/T-Rex/releases/download/0.10.2/t-rex-0.10.2-win-cuda10.0.zip"
-
-$Commands = [PSCustomObject]@{
- "balloon" = " -a balloon -i 23" #Balloon
- "astralhash" = " -a astralhash -i 23" #Astralhash
- "jeonghash" = " -a jeonghash -i 23" #Jeonghash
- "padihash" = " -a padihash -i 23" #Padihash
- "pawelhash" = " -a pawelhash -i 23" #Pawelhash
- "polytimos" = " -a polytimos -i 25" #Poly
- "bcd" = " -a bcd -i 24" #Bcd
- #"skunk" = " -a skunk" #Skunk
- "bitcore" = " -a bitcore -i 25" #Bitcore
- "geek" = " -a geek -i 23" #Geekcash
- #"lyra2z" = "" #Lyra2z
- "c11" = " -a c11 -i 24" #C11
- "x17" = " -a x17 -i 24" #X17
- "x16s" = " -a x16s -i 24" #X16s
- "x16r" = " -a x16r -i 24" #X16r
- "x16rt" = " -a x16rt -i 24" #X16rt
- "sonoa" = " -a sonoa -i 23" #Sonoa
- #"hmq1725" = " -a hmq1725 -i 23" #Hmq1725
- "dedal" = " -a dedal -i 23" #Dedal
- "sha256t" = " -a sha256t -i 26" #Sha256t
- "sha256q" = " -a sha256q -i 23" #Sha256q
- "x21s" = " -a x21s -i 23 " #X21s
- "x22i" = " -a x22i -i 23" #X22i
- "timetravel" = " -a timetravel -i 25" #Timetravel
- "tribus" = " -a tribus -i 23" #Tribus
- "veil" = " -a x16rt -i 24" #Veil
- "mtp" = " -a mtp -i 21" #MTP
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "--no-watchdog --no-nvml -b 127.0.0.1:$($Variables.NVIDIAMinerAPITCPPort) -d $($Config.SelGPUCC) -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_) --quiet -r 10 --cpu-priority 5"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * .99} # substract 1% devfee
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/OptionalMiners/ttminer.ps1 b/OptionalMiners/ttminer.ps1
deleted file mode 100644
index 537183b3ef..0000000000
--- a/OptionalMiners/ttminer.ps1
+++ /dev/null
@@ -1,33 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-TTMiner222\TT-Miner.exe"
-$Uri = "https://nemosminer.com/data/optional/TT-Miner-2.2.2.7z"
-
-$Commands = [PSCustomObject]@{
- "progpow" = " -a PROGPOW"
- #"mtp" = " -a MTP"
- #"ethash" = " -a ETHASH"
- "ubqhash" = " -a UBQHASH"
- #"myr-gr" = " -a MYRGR "
- #"lyra2v3" = " -a LYRA2V3"
- #"lyra2rev3" = " -a LYRA2V3"
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "-d $($Config.SelGPUDSTM) --api-bind 127.0.0.1:$($Variables.NVIDIAMinerAPITCPPort) -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * .99} # substract 1% devfee
- API = "TTminer"
- Port = $Variables.NVIDIAMinerAPITCPPort #4068
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/OptionalMiners/xmrig.ps1 b/OptionalMiners/xmrig.ps1
deleted file mode 100644
index f0b225e9f7..0000000000
--- a/OptionalMiners/xmrig.ps1
+++ /dev/null
@@ -1,28 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-XMRig2143\xmrig-nvidia.exe"
-$Uri = "https://github.com/xmrig/xmrig-nvidia/releases/download/v2.14.3/xmrig-nvidia-2.14.3-cuda10_1-win64.zip"
-
-$Commands = [PSCustomObject]@{
- #"cryptonightr" = " --nicehash" #cryptonight/r (NiceHash)
- #"cryptonight-monero" = "" #cryptonight/r (Mining Pool Hub)
-}
-$Port = 4068 #2222
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
-$Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "-R 1 --cuda-devices=$($Config.SelGPUCC) -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_) -a cryptonight/r --keepalive --api-port=$($Variables.NVIDIAMinerAPITCPPort) --donate-level=1"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * .99} # substract 1% devfee
- API = "XMRig"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/OptionalMiners/xmrigcpu.ps1 b/OptionalMiners/xmrigcpu.ps1
deleted file mode 100644
index 313695ae5c..0000000000
--- a/OptionalMiners/xmrigcpu.ps1
+++ /dev/null
@@ -1,32 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\CPU-XMRig\xmrig.exe"
-$Uri = "https://github.com/xmrig/xmrig/releases/download/v2.6.2/xmrig-2.6.2-msvc-win64.zip"
-
-$Commands = [PSCustomObject]@{
- #"cryptonight" = "" #Cryptonight
- #"cryptonight-lite" = "" #Cryptonight-lite
- #"cryptonight-heavy" = "" #Cryptonight-Heavy
- #"cryptonightV7" = "" #CryptonightV7
-}
-
-$ThreadCount = $ThreadCount = $Variables.ProcessorCount - 2
-
-$Port = $Variables.CPUMinerAPITCPPort #2222
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "CPU"
- Path = $Path
- # Arguments = "-t $($ThreadCount) -a $_ -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_) --api-port $($port) --donate-level 1"
- Arguments = "-a $_ -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_) --api-port $($port) --donate-level 1"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Week * .99} # substract 1% devfee
- API = "XMRig"
- Port = $Port
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- }
-}
diff --git a/OptionalMiners/zealotenemy.ps1 b/OptionalMiners/zealotenemy.ps1
deleted file mode 100644
index 2b536f1dbe..0000000000
--- a/OptionalMiners/zealotenemy.ps1
+++ /dev/null
@@ -1,42 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-$Path = ".\Bin\NVIDIA-zealotenemy128\z-enemy.exe"
-$Uri = "https://nemosminer.com/data/optional/z-enemy.1-28-cuda10.0.7z"
-
-$Commands = [PSCustomObject]@{
- "aergo" = " -i 23" #AeriumX
- #"bcd" = "" #Bcd
- #"phi" = " -i 22" #Phi
- #"phi2" = "" #Phi2
- #"poly" = "" #Polytimos
- #"bitcore" = "" #Bitcore
- #"x16r" = "" #X16r
- #"x16s" = "" #X16s
- #"sonoa" = "" #SonoA
- "skunk" = "" #Skunk
- #"timetravel" = "" #Timetravel
- #"tribus" = "" #Tribus
- #"c11" = "" #C11
- "xevan" = " -i 22" #Xevan
- #"x17" = "" #X17
- "hex" = " -i 24" #Hex
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Commands | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = Get-Algorithm($_)
- [PSCustomObject]@{
- Type = "NVIDIA"
- Path = $Path
- Arguments = "-b $($Variables.NVIDIAMinerAPITCPPort) -d $($Config.SelGPUCC) -R 1 -q -a $_ -o stratum+tcp://$($Pools.($Algo).Host):$($Pools.($Algo).Port) -u $($Pools.($Algo).User) -p $($Pools.($Algo).Pass)$($Commands.$_)"
- HashRates = [PSCustomObject]@{($Algo) = $Stats."$($Name)_$($Algo)_HashRate".Day * .99} # substract 1% devfee
- API = "ccminer"
- Port = $Variables.NVIDIAMinerAPITCPPort
- Wrap = $false
- URI = $Uri
- User = $Pools.($Algo).User
- Host = $Pools.($Algo).Host
- Coin = $Pools.($Algo).Coin
- }
-}
diff --git a/Pools/Blockmasters.ps1 b/Pools/Blockmasters.ps1
new file mode 100644
index 0000000000..9b5f77059b
--- /dev/null
+++ b/Pools/Blockmasters.ps1
@@ -0,0 +1,94 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: Blockmasters.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+using module ..\Includes\Include.psm1
+
+param(
+ [PSCustomObject]$Config,
+ [PSCustomObject]$PoolsConfig,
+ [String]$PoolVariant,
+ [Hashtable]$Variables
+)
+
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$PoolConfig = $PoolsConfig.(Get-PoolBaseName $Name)
+$PriceField = $Variables.PoolData.$Name.Variant.$PoolVariant.PriceField
+$DivisorMultiplier = $Variables.PoolData.$Name.Variant.$PoolVariant.DivisorMultiplier
+$PayoutCurrency = $PoolConfig.Wallets.Keys | Select-Object -First 1
+$Wallet = $PoolConfig.Wallets.$PayoutCurrency
+
+If ($DivisorMultiplier -and $PriceField -and $Wallet) {
+
+ Try {
+ $Request = Get-Content ((Split-Path -Parent (Get-Item $MyInvocation.MyCommand.Path).Directory) + "\Brains\$($Name)\$($Name).json") -ErrorAction Stop | ConvertFrom-Json
+ }
+ Catch { Return }
+
+ If (-not $Request) { Return }
+
+ $HostSuffix = "blockmasters.co"
+
+ $Request.PSObject.Properties.Name | Where-Object { $Request.$_.$PriceField -gt 0 } | ForEach-Object {
+ $Algorithm = $Request.$_.name
+ $Algorithm_Norm = Get-Algorithm $Algorithm
+ $Currency = "$($Request.$_.currency)".Trim()
+ $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
+ $Fee = $Request.$_.Fees / 100
+ $PoolPort = $Request.$_.port
+ $Updated = $Request.$_.Updated
+ $Workers = $Request.$_.workers
+
+ # Add coin name
+ If ($Request.$_.CoinName -and $Currency -and -not (Get-CoinName $Currency)) {
+ Add-CoinName -Currency $Currency -CoinName $Request.$_.CoinName
+ }
+
+ $Stat = Set-Stat -Name "$($PoolVariant)_$($Algorithm_Norm)$(If ($Currency) { "-$($Currency)" })_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor) -FaultDetection $false
+
+ ForEach ($Region in $PoolConfig.Region) {
+ $Region_Norm = Get-Region $Region
+
+ [PSCustomObject]@{
+ Name = [String]$PoolVariant
+ BaseName = [String]$Name
+ Algorithm = [String]$Algorithm_Norm
+ Currency = [String]$Currency
+ Price = [Double]$Stat.Live
+ StablePrice = [Double]$Stat.Week
+ Accuracy = [Double](1 - [Math]::Min([Math]::Abs($Stat.Week_Fluctuation), 1))
+ EarningsAdjustmentFactor = [Double]$PoolConfig.EarningsAdjustmentFactor
+ Host = "$($Region).$($HostSuffix)" -replace "^us\."
+ Port = [UInt16]$PoolPort
+ User = [String]$Wallet
+ Pass = "$($PoolConfig.WorkerName),c=$PayoutCurrency"
+ Region = [String]$Region_Norm
+ SSL = $false
+ Fee = [Decimal]$Fee
+ Updated = [DateTime]$Updated
+ Workers = [Int]$Workers
+ }
+ }
+ }
+}
diff --git a/Pools/HiveON.ps1 b/Pools/HiveON.ps1
new file mode 100644
index 0000000000..b226b6f1a9
--- /dev/null
+++ b/Pools/HiveON.ps1
@@ -0,0 +1,84 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: HiveOn.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+using module ..\Includes\Include.psm1
+
+param(
+ [PSCustomObject]$Config,
+ [PSCustomObject]$PoolsConfig,
+ [String]$PoolVariant,
+ [Hashtable]$Variables
+)
+
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$PoolConfig = $PoolsConfig.(Get-PoolBaseName $Name)
+
+If ($PoolConfig.Wallets) {
+ Try {
+ $Request = Invoke-RestMethod -Uri "https://hiveon.net/api/v1/stats/pool" -Headers @{ "Cache-Control" = "no-cache" } -SkipCertificateCheck -TimeoutSec $Config.PoolTimeout
+ }
+ Catch { Return }
+
+ If (-not $Request) { Return }
+
+ $Request.cryptoCurrencies | Where-Object { $PoolConfig.Wallets.($_.Name) -and $Variables.Rates.($_.name).BTC } | ForEach-Object {
+ $Currency = "$($_.name)".Trim()
+ $Algorithm_Norm = Get-Algorithm $Currency
+ $Divisor = [Double]$_.profitPerPower
+ $Workers = $Request.stats.($_.name).workers
+ $_.Servers | ForEach-Object { $_.Region = $_.Region -replace 'all', 'N/A' }
+
+ # Add coin name
+ If ($_.title -and $Currency -and -not (Get-CoinName $Currency)) {
+ Add-CoinName -Currency $Currency -CoinName $_.title
+ }
+
+ $Stat = Set-Stat -Name "$($PoolVariant)_$($Algorithm_Norm)$(If ($Currency) { "-$($Currency)" })_Profit" -Value ([Double]$Request.stats.($_.name).expectedReward24H * $Variables.Rates.($_.name).BTC / $Divisor) -FaultDetection $false
+
+ ForEach ($Server in ($_.Servers | Where-Object { $_.Region -in $PoolConfig.Region -or $_.Region -eq "N/A" } )) {
+ $Region_Norm = Get-Region $Server.Region
+
+ [PSCustomObject]@{
+ Name = [String]$PoolVariant
+ BaseName = [String]$Name
+ Algorithm = [String]$Algorithm_Norm
+ Currency = [String]$Currency
+ Price = [Double]$Stat.Live
+ StablePrice = [Double]$Stat.Week
+ Accuracy = [Double](1 - [Math]::Min([Math]::Abs($Stat.Week_Fluctuation), 1))
+ EarningsAdjustmentFactor = [Double]$PoolConfig.EarningsAdjustmentFactor
+ Host = [String]$Server.host
+ Port = [UInt16]$Server.ports[0]
+ User = "$($PoolConfig.Wallets.$Currency).$($PoolConfig.WorkerName)"
+ Pass = "x"
+ Region = [String]$Region_Norm
+ SSL = $false
+ Fee = [Decimal]0
+ Updated = [DateTime]$Stat.Updated
+ Workers = [Int]$Workers
+ }
+ }
+ }
+}
diff --git a/Pools/MiningPoolHub.ps1 b/Pools/MiningPoolHub.ps1
new file mode 100644
index 0000000000..13c7157287
--- /dev/null
+++ b/Pools/MiningPoolHub.ps1
@@ -0,0 +1,152 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: MiningPoolHub.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+using module ..\Includes\Include.psm1
+
+param(
+ [PSCustomObject]$Config,
+ [PSCustomObject]$PoolsConfig,
+ [String]$PoolVariant,
+ [Hashtable]$Variables
+)
+
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$PoolConfig = $PoolsConfig.(Get-PoolBaseName $Name)
+
+If ($PoolConfig.UserName) {
+ If ($PoolVariant -match "Coins$") {
+ Try {
+ $Request = Invoke-RestMethod -Uri "https://miningpoolhub.com/index.php?page=api&action=getminingandprofitsstatistics" -Headers @{ "Cache-Control" = "no-cache" } -SkipCertificateCheck -TimeoutSec $Config.PoolTimeout
+ }
+ Catch { Return }
+
+ If (-not $Request) { Return }
+
+ $Divisor = 1000000000
+
+ $User = "$($PoolConfig.UserName).$($($PoolConfig.WorkerName -replace "^ID="))"
+
+ $Request.return | Where-Object profit | ForEach-Object {
+ $Current = $_
+
+ $Algorithm_Norm = Get-Algorithm $_.algo
+ $Currency = "$($Current.symbol)".Trim()
+ $Fee = [Decimal]($_.Fee / 100)
+ $Port = $Current.port
+
+ # Add coin name
+ If ($Current.coin_name -and $Currency -and -not (Get-CoinName $Currency)) {
+ Add-CoinName -Currency $Currency -CoinName $Current.coin_name
+ }
+
+ $Stat = Set-Stat -Name "$($PoolVariant)_$($Algorithm_Norm)-$($Currency)_Profit" -Value ([Decimal]$_.profit / $Divisor) -FaultDetection $false
+
+ # Temp fix
+ $PoolRegions = If ($Current.host_list.split(";").count -eq 1) { @("N/A") } Else { $PoolConfig.Region }
+ Switch ($Algorithm_Norm) {
+ # "Ethash" { $PoolRegions = @($PoolConfig.Region | Where-Object { $_ -in @("Asia", "US") }) } # temp fix
+ "Neoscrypt" { $Current.host_list = $Current.host } # Error in API
+ "Lyra2RE2" { $Current.host_list = $Current.host } # Error in API
+ "Skein" { $Current.host_list = $Current.host } # Error in API
+ "VertHash" { $Current.host_list = $Current.host } # Error in API
+ "Yescrypt" { $Current.host_list = $Current.host } # Error in API
+ # Default { $Port = $Current.port }
+ }
+
+ ForEach ($Region in $PoolRegions) {
+ $Region_Norm = Get-Region $Region
+
+ [PSCustomObject]@{
+ Name = [String]$PoolVariant
+ BaseName = [String]$Name
+ Algorithm = [String]$Algorithm_Norm
+ Currency = [String]$Currency
+ Price = [Double]$Stat.Live * (1 - [Math]::Min($Stat.Day_Fluctuation, 1)) + $Stat.Day * [Math]::Min($Stat.Day_Fluctuation, 1)
+ StablePrice = [Double]$Stat.Week
+ Accuracy = [Double](1 - $Stat.Week_Fluctuation)
+ EarningsAdjustmentFactor = [Double]$PoolConfig.EarningsAdjustmentFactor
+ Host = [String]($Current.host_list.split(";") | Sort-Object -Descending { $_ -ilike "$Region*" } | Select-Object -First 1)
+ Port = [UInt16]$Port
+ User = [String]$User
+ Pass = "x"
+ Region = [String]$Region_Norm
+ SSL = $false
+ Fee = $Fee
+ }
+ }
+ }
+ }
+ Else {
+ Try {
+ $Request = Invoke-RestMethod -Uri "https://miningpoolhub.com/index.php?page=api&action=getautoswitchingandprofitsstatistics" -Headers @{ "Cache-Control" = "no-cache" } -SkipCertificateCheck -TimeoutSec $Config.PoolTimeout
+ }
+ Catch { Return }
+
+ If (-not $Request) { Return }
+
+ $Divisor = 1000000000
+
+ $User = "$($PoolConfig.UserName).$($($PoolConfig.WorkerName -replace "^ID="))"
+
+ $Request.return | Where-Object profit | ForEach-Object {
+ $Current = $_
+
+ $Algorithm_Norm = Get-Algorithm $_.algo
+ $Port = $Current.algo_switch_port
+
+ $Stat = Set-Stat -Name "$($PoolVariant)_$($Algorithm_Norm)_Profit" -Value ([Decimal]$_.profit / $Divisor) -FaultDetection $false
+
+ # Temp fix
+ $PoolRegions = If ($Current.all_host_list.split(";").count -eq 1) { @("N/A") } Else { $PoolConfig.Region }
+ Switch ($Algorithm_Norm) {
+ # "Ethash" { $PoolRegions = @($PoolConfig.Region | Where-Object { $_ -in @("Asia", "US") }) } # temp fix
+ "VertHash" { $Port = 20534 }
+ # Default { $Port = $Current.algo_switch_port }
+ }
+
+ ForEach ($Region in $PoolRegions) {
+ $Region_Norm = Get-Region $Region
+
+ [PSCustomObject]@{
+ Name = [String]$PoolVariant
+ BaseName = [String]$Name
+ Algorithm = [String]$Algorithm_Norm
+ Currency = [String]$Current.current_mining_coin_symbol
+ Price = [Double]$Stat.Live * (1 - [Math]::Min($Stat.Day_Fluctuation, 1)) + $Stat.Day * (0 + [Math]::Min($Stat.Day_Fluctuation, 1))
+ StablePrice = [Double]$Stat.Week
+ Accuracy = [Double](1 - [Math]::Min([Math]::Abs($Stat.Week_Fluctuation), 1))
+ EarningsAdjustmentFactor = [Double]$PoolConfig.EarningsAdjustmentFactor
+ Host = [String]($Current.all_host_list.split(";") | Sort-Object -Descending { $_ -ilike "$Region*" } | Select-Object -First 1)
+ Port = [UInt16]$Port
+ User = [String]$User
+ Pass = "x"
+ Region = [String]$Region_Norm
+ SSL = $false
+ Fee = [Decimal]$PoolConfig.Fee
+ }
+ }
+ }
+ }
+}
diff --git a/Pools/NLPool.ps1 b/Pools/NLPool.ps1
new file mode 100644
index 0000000000..e359c155cd
--- /dev/null
+++ b/Pools/NLPool.ps1
@@ -0,0 +1,95 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: NLPool.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+using module ..\Includes\Include.psm1
+
+param(
+ [PSCustomObject]$Config,
+ [PSCustomObject]$PoolsConfig,
+ [String]$PoolVariant,
+ [Hashtable]$Variables
+)
+
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$PoolConfig = $PoolsConfig.(Get-PoolBaseName $Name)
+$PriceField = $Variables.PoolData.$Name.Variant.$PoolVariant.PriceField
+$DivisorMultiplier = $Variables.PoolData.$Name.Variant.$PoolVariant.DivisorMultiplier
+$PayoutCurrency = $PoolConfig.Wallets.Keys | Select-Object -First 1
+$Wallet = $PoolConfig.Wallets.$PayoutCurrency
+
+If ($DivisorMultiplier -and $PriceField -and $Wallet) {
+
+ Try {
+ $Request = Get-Content ((Split-Path -Parent (Get-Item $MyInvocation.MyCommand.Path).Directory) + "\Brains\$($Name)\$($Name).json") -ErrorAction Stop | ConvertFrom-Json
+ }
+ Catch { Return }
+
+ If (-not $Request) { Return }
+
+ $HostSuffix = "mine.nlpool.nl"
+
+ $Request.PSObject.Properties.Name | Where-Object { [Double]$Request.$_.$PriceField -gt 0 } | ForEach-Object {
+ $Algorithm = $Request.$_.name
+ $Algorithm_Norm = Get-Algorithm $Algorithm
+ $Currency = "$($Request.$_.currency)".Trim()
+ $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
+ $Fee = $Request.$_.Fees / 100
+ $PoolHost = $HostSuffix
+ $PoolPort = $Request.$_.port
+ $Updated = $Request.$_.Updated
+ $Workers = $Request.$_.workers
+
+ # Add coin name
+ If ($Request.$_.CoinName -and $Currency -and -not (Get-CoinName $Currency)) {
+ Add-CoinName -Currency $Currency -CoinName $Request.$_.CoinName
+ }
+
+ $Stat = Set-Stat -Name "$($PoolVariant)_$($Algorithm_Norm)$(If ($Currency) { "-$($Currency)" })_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor) -FaultDetection $false
+
+ ForEach ($Region in $PoolConfig.Region) {
+ $Region_Norm = Get-Region $Region
+
+ [PSCustomObject]@{
+ Name = [String]$PoolVariant
+ BaseName = [String]$Name
+ Algorithm = [String]$Algorithm_Norm
+ Currency = [String]$Currency
+ Price = [Double]$Stat.Live
+ StablePrice = [Double]$Stat.Week
+ Accuracy = [Double](1 - [Math]::Min([Math]::Abs($Stat.Week_Fluctuation), 1))
+ EarningsAdjustmentFactor = [Double]$PoolConfig.EarningsAdjustmentFactor
+ Host = [String]$PoolHost
+ Port = [UInt16]$PoolPort
+ User = [String]$Wallet
+ Pass = "$($PoolConfig.WorkerName),c=$PayoutCurrency"
+ Region = [String]$Region_Norm
+ SSL = $false
+ Fee = [Decimal]$Fee
+ Updated = [DateTime]$Updated
+ Workers = [Int]$Workers
+ }
+ }
+ }
+}
diff --git a/Pools/NiceHash.ps1 b/Pools/NiceHash.ps1
new file mode 100644
index 0000000000..30cdb44546
--- /dev/null
+++ b/Pools/NiceHash.ps1
@@ -0,0 +1,115 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: NiceHash.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+using module ..\Includes\Include.psm1
+
+param(
+ [PSCustomObject]$Config,
+ [PSCustomObject]$PoolsConfig,
+ [String]$PoolVariant,
+ [Hashtable]$Variables
+)
+
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$PoolConfig = $PoolsConfig.(Get-PoolBaseName $Name)
+$Fee = $PoolConfig.Variant.$PoolVariant.Fee
+$PayoutCurrency = $PoolConfig.Variant.$PoolVariant.PayoutCurrency
+$Regions = If ($Config.UseAnycast -and $PoolConfig.Region -contains "N/A (Anycast)") { "N/A (Anycast)" } Else { $PoolConfig.Region | Where-Object { $_ -ne "N/A (Anycast)" } }
+$Wallet = $PoolConfig.Variant.$PoolVariant.Wallets.$PayoutCurrency
+$User = "$Wallet.$($PoolConfig.WorkerName -replace "^ID=")"
+
+If ($Wallet) {
+ Try {
+ $Request = Invoke-RestMethod -Uri "https://api2.nicehash.com/main/api/v2/public/simplemultialgo/info/" -Headers @{ "Cache-Control" = "no-cache" } -SkipCertificateCheck -TimeoutSec $Config.PoolTimeout
+ $RequestAlgodetails = Invoke-RestMethod -Uri "https://api2.nicehash.com/main/api/v2/mining/algorithms/" -Headers @{ "Cache-Control" = "no-cache" } -SkipCertificateCheck -TimeoutSec $Config.PoolTimeout
+ $Request.miningAlgorithms | ForEach-Object { $Algorithm = $_.Algorithm; $_ | Add-Member -Force @{ algodetails = $RequestAlgodetails.miningAlgorithms | Where-Object { $_.Algorithm -eq $Algorithm } } }
+ }
+ Catch { Return }
+
+ If (-not $Request) { Return }
+
+ $HostSuffix = "nicehash.com"
+
+ $Request.miningAlgorithms | Where-Object speed -GT 0 | Where-Object { $_.algodetails.order -gt 0 } | ForEach-Object {
+ $Algorithm = $_.Algorithm
+ $Algorithm_Norm = Get-Algorithm $Algorithm
+
+ $Currency = Switch -Regex ($Algorithm_Norm) {
+ "Autolykos2" { "ERG" }
+ "BeamV3" { "BEAM" }
+ "CuckooCycle" { "AE" }
+ "Cuckaroo29" { "XBG" }
+ "Cuckarood29" { "MWC" }
+ "^Cuckatoo31$|^Cuckatoo32$" { "GRIN" }
+ "CryptonightR" { "SUMO" }
+ "Eaglesong" { "CKB" }
+ "Equihash1254" { "FLUX" }
+ "EquihashBTG" { "BTG" }
+ "Ethash" { "ETH" }
+ "Handshake" { "HNS" }
+ "KawPoW" { "RVN" }
+ "Lbry" { "LBC" }
+ "Octopus" { "CFX" }
+ "RandomX" { "XMR" }
+ Default { "" }
+ }
+
+ $Divisor = 100000000
+
+ $Stat = Set-Stat -Name "$($PoolVariant)_$($Algorithm_Norm)_Profit" -Value ([Double]$_.paying / $Divisor) -FaultDetection $false
+
+ ForEach ($Region in $Regions) {
+ $Region_Norm = Get-Region $Region
+
+ If ($Region -eq "N/A (Anycast)") {
+ $PoolHost = "$Algorithm.Auto.$HostSuffix"
+ $PoolPort = 9200
+ }
+ Else {
+ $PoolHost = "$Algorithm.$Region.$HostSuffix"
+ $PoolPort = $_.algodetails.port
+ }
+
+ [PSCustomObject]@{
+ Name = [String]$PoolVariant
+ BaseName = [String]$Name
+ Algorithm = [String]$Algorithm_Norm
+ Currency = [String]$Currency
+ Price = [Double]$Stat.Live
+ StablePrice = [Double]$Stat.Week
+ Accuracy = [Double](1 - [Math]::Min([Math]::Abs($Stat.Minute_5_Fluctuation), 1)) # Use short timespan to counter price peaks
+ EarningsAdjustmentFactor = [Double]$PoolConfig.EarningsAdjustmentFactor
+ Host = [String]$PoolHost.ToLower()
+ Port = [UInt16]$PoolPort
+ User = [String]$User
+ Pass = "x"
+ Region = [String]$Region_Norm
+ SSL = $false
+ Fee = [Decimal]$Fee
+ Updated = [DateTime]$Stat.Updated
+ }
+ }
+ }
+}
diff --git a/Pools/ProHashing.ps1 b/Pools/ProHashing.ps1
new file mode 100644
index 0000000000..bfe2a5d452
--- /dev/null
+++ b/Pools/ProHashing.ps1
@@ -0,0 +1,91 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: ProHashing.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+using module ..\Includes\Include.psm1
+
+param(
+ [PSCustomObject]$Config,
+ [PSCustomObject]$PoolsConfig,
+ [String]$PoolVariant,
+ [Hashtable]$Variables
+)
+
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$PoolConfig = $PoolsConfig.(Get-PoolBaseName $Name)
+$PriceField = $Variables.PoolData.$Name.Variant.$PoolVariant.PriceField
+$DivisorMultiplier = $Variables.PoolData.$Name.Variant.$PoolVariant.DivisorMultiplier
+
+If ($DivisorMultiplier -and $PriceField -and $PoolConfig.UserName) {
+ Try {
+ $Request = Get-Content ((Split-Path -Parent (Get-Item $MyInvocation.MyCommand.Path).Directory) + "\Brains\$($Name)\$($Name).json") -ErrorAction Stop | ConvertFrom-Json
+ }
+ Catch { Return }
+
+ If (-not $Request) { Return }
+
+ $PoolHost = "prohashing.com"
+
+ $Request.PSObject.Properties.Name | Where-Object { $Request.$_.$PriceField -gt 0 } -ErrorAction Stop | ForEach-Object {
+ $Algorithm = $Request.$_.name
+ $Algorithm_Norm = Get-Algorithm $Algorithm
+ $Currency = "$($Request.$_.currency)".Trim()
+ $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
+ $Fee = $Request.$_."$($PoolConfig.MiningMode)_fee"
+ $Pass = @("a=$($Algorithm.ToLower())", "n=$($PoolConfig.WorkerName)", "o=$($PoolConfig.UserName)") -join ','
+ $PoolPort = $Request.$_.port
+
+ # Add coin name
+ If ($Request.$_.CoinName -and $Currency -and -not (Get-CoinName $Currency)) {
+ Add-CoinName -Currency $Currency -CoinName $Request.$_.CoinName
+ }
+
+ $Stat = Set-Stat -Name "$($PoolVariant)_$($Algorithm_Norm)$(If ($Currency) { "-$($Currency)" })_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor) -FaultDetection $false
+
+ $Regions = If ($Algorithm_Norm -in @("Chia", "Etchash", "Ethash", "EthashLowMem")) { "US" } Else { $PoolConfig.Region }
+
+ ForEach ($Region in $Regions) {
+ $Region_Norm = Get-Region $Region
+
+ [PSCustomObject]@{
+ Name = [String]$PoolVariant
+ BaseName = [String]$Name
+ Algorithm = [String]$Algorithm_Norm
+ Currency = [String]$Currency
+ Price = [Double]$Stat.Live
+ StablePrice = [Double]$Stat.Week
+ Accuracy = [Double](1 - [Math]::Min([Math]::Abs($Stat.Week_Fluctuation), 1))
+ EarningsAdjustmentFactor = [Double]$PoolConfig.EarningsAdjustmentFactor
+ Host = "$(If ($Region -eq "EU") { "eu." })$PoolHost"
+ Port = [UInt16]$PoolPort
+ User = [String]$PoolConfig.UserName
+ Pass = [String]$Pass
+ Region = [String]$Region_Norm
+ SSL = $false
+ Fee = [Decimal]$Fee
+ Updated = [DateTime]$Stat.Updated
+ }
+ }
+ }
+}
diff --git a/Pools/TonPool.ps1 b/Pools/TonPool.ps1
new file mode 100644
index 0000000000..096a0a26bf
--- /dev/null
+++ b/Pools/TonPool.ps1
@@ -0,0 +1,90 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: TonPool.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+using module ..\Includes\Include.psm1
+
+param(
+ [PSCustomObject]$Config,
+ [PSCustomObject]$PoolsConfig,
+ [String]$PoolVariant,
+ [Hashtable]$Variables
+)
+
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$PoolConfig = $PoolsConfig.(Get-PoolBaseName $Name)
+$PriceField = $Variables.PoolData.$Name.Variant.$PoolVariant.PriceField
+$DivisorMultiplier = $Variables.PoolData.$Name.Variant.$PoolVariant.DivisorMultiplier
+$PayoutCurrency = $PoolConfig.Wallets.Keys | Select-Object -First 1
+$Wallet = $PoolConfig.Wallets.$PayoutCurrency
+
+If ($DivisorMultiplier -and $PriceField -and $Wallet -and $Variables.Rates.BTC.TON) {
+
+ Try {
+ $Request = Invoke-RestMethod -Uri "https://next.ton-pool.com/stats" -Headers @{ "Cache-Control" = "no-cache" } -SkipCertificateCheck -TimeoutSec $Config.PoolTimeout
+ }
+ Catch { Return }
+
+ If (-not $Request) { Return }
+
+ $HostSuffix = "1.stratum.ton-pool.com/stratum"
+
+ $Algorithm = "TonPoW"
+ $Algorithm_Norm = Get-Algorithm $Algorithm
+ $CoinName = "TonCoin"
+ $Currency = "TON"
+ $Divisor = $DivisorMultiplier * $Variables.Rates.BTC.TON
+ $Fee = 0.05
+ $PoolPort = 443
+
+ # Add coin name
+ If ($CoinName -and $Currency -and -not (Get-CoinName $Currency)) {
+ Add-CoinName -Currency $Currency -CoinName $CoinName
+ }
+
+ $Stat = Set-Stat -Name "$($PoolVariant)_$($Algorithm_Norm)_Profit" -Value ([Double]$Request.income.$PriceField / $Divisor) -FaultDetection $false
+
+ ForEach ($Region in $PoolConfig.Region) {
+ $Region_Norm = Get-Region $Region
+
+ [PSCustomObject]@{
+ Name = [String]$PoolVariant
+ BaseName = [String]$Name
+ Algorithm = [String]$Algorithm_Norm
+ Currency = [String]$Currency
+ Price = [Double]$Stat.Live
+ StablePrice = [Double]$Stat.Week
+ Accuracy = [Double](1 - [Math]::Min([Math]::Abs($Stat.Week_Fluctuation), 1))
+ EarningsAdjustmentFactor = [Double]$PoolConfig.EarningsAdjustmentFactor
+ Host = "$($Region)$($HostSuffix)"
+ Port = [UInt16]$PoolPort
+ User = [String]$Wallet
+ Pass = "x"
+ Region = [String]$Region_Norm
+ SSL = $true
+ Fee = [Decimal]$Fee
+ Updated = [DateTime]$Stat.Updated
+ }
+ }
+}
diff --git a/Pools/TonWhales.ps1 b/Pools/TonWhales.ps1
new file mode 100644
index 0000000000..2a4cd10c98
--- /dev/null
+++ b/Pools/TonWhales.ps1
@@ -0,0 +1,90 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: TonPool.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+using module ..\Includes\Include.psm1
+
+param(
+ [PSCustomObject]$Config,
+ [PSCustomObject]$PoolsConfig,
+ [String]$PoolVariant,
+ [Hashtable]$Variables
+)
+
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$PoolConfig = $PoolsConfig.(Get-PoolBaseName $Name)
+$PriceField = $Variables.PoolData.$Name.Variant.$PoolVariant.PriceField
+$DivisorMultiplier = $Variables.PoolData.$Name.Variant.$PoolVariant.DivisorMultiplier
+$PayoutCurrency = $PoolConfig.Wallets.Keys | Select-Object -First 1
+$Wallet = $PoolConfig.Wallets.$PayoutCurrency
+
+If ($DivisorMultiplier -and $PriceField -and $Wallet -and $Variables.Rates.BTC.TON) {
+
+ Try {
+ $Request = Invoke-RestMethod -Uri "https://ton-reports-24d2v.ondigitalocean.app/report/pool-profitability" -Headers @{ "Cache-Control" = "no-cache" } -SkipCertificateCheck -TimeoutSec $Config.PoolTimeout
+ }
+ Catch { Return }
+
+ If (-not $Request) { Return }
+
+ $HostSuffix = "whalestonpool.com"
+
+ $Algorithm = "TonPoW"
+ $Algorithm_Norm = Get-Algorithm $Algorithm
+ $CoinName = "TonCoin"
+ $Currency = "TON"
+ $Divisor = $DivisorMultiplier * $Variables.Rates.BTC.TON
+ $Fee = 0
+ $PoolPort = 4001
+
+ # Add coin name
+ If ($CoinName -and $Currency -and -not (Get-CoinName $Currency)) {
+ Add-CoinName -Currency $Currency -CoinName $CoinName
+ }
+
+ $Stat = Set-Stat -Name "$($PoolVariant)_$($Algorithm_Norm)_Profit" -Value ([Double]$Request.$PriceField / $Divisor) -FaultDetection $false
+
+ ForEach ($Region in $PoolConfig.Region) {
+ $Region_Norm = Get-Region $Region
+
+ [PSCustomObject]@{
+ Name = [String]$PoolVariant
+ BaseName = [String]$Name
+ Algorithm = [String]$Algorithm_Norm
+ Currency = [String]$Currency
+ Price = [Double]$Stat.Live
+ StablePrice = [Double]$Stat.Week
+ Accuracy = [Double](1 - [Math]::Min([Math]::Abs($Stat.Week_Fluctuation), 1))
+ EarningsAdjustmentFactor = [Double]$PoolConfig.EarningsAdjustmentFactor
+ Host = $HostSuffix
+ Port = [UInt16]$PoolPort
+ User = [String]$Wallet
+ Pass = "x"
+ Region = [String]$Region_Norm
+ SSL = $true
+ Fee = [Decimal]$Fee
+ Updated = [DateTime]$Stat.Updated
+ }
+ }
+}
diff --git a/Pools/ZPool.ps1 b/Pools/ZPool.ps1
new file mode 100644
index 0000000000..56d7d78760
--- /dev/null
+++ b/Pools/ZPool.ps1
@@ -0,0 +1,94 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: ZPool.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+using module ..\Includes\Include.psm1
+
+param(
+ [PSCustomObject]$Config,
+ [PSCustomObject]$PoolsConfig,
+ [String]$PoolVariant,
+ [Hashtable]$Variables
+)
+
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$PoolConfig = $PoolsConfig.(Get-PoolBaseName $Name)
+$PriceField = $Variables.PoolData.$Name.Variant.$PoolVariant.PriceField
+$DivisorMultiplier = $Variables.PoolData.$Name.Variant.$PoolVariant.DivisorMultiplier
+$PayoutCurrency = $PoolConfig.Wallets.Keys | Select-Object -First 1
+$Wallet = $PoolConfig.Wallets.$PayoutCurrency
+
+If ($DivisorMultiplier -and $PriceField -and $Wallet) {
+
+ Try {
+ $Request = Get-Content ((Split-Path -Parent (Get-Item $MyInvocation.MyCommand.Path).Directory) + "\Brains\$($Name)\$($Name).json") -ErrorAction Stop | ConvertFrom-Json
+ }
+ Catch { Return }
+
+ If (-not $Request) { Return }
+
+ $HostSuffix = "mine.zpool.ca"
+
+ $Request.PSObject.Properties.Name | Where-Object { $Request.$_.$PriceField -gt 0 } | ForEach-Object {
+ $Algorithm = $_
+ $Algorithm_Norm = Get-Algorithm $Algorithm
+ $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
+ $Currency = "$($Request.$_.currency)".Trim()
+ $Fee = $Request.$_.Fees / 100
+ $PoolPort = $Request.$_.port
+ $Updated = $Request.$_.Updated
+ $Workers = $Request.$_.workers
+
+ # Add coin name
+ If ($Request.$_.CoinName -and $Currency -and -not (Get-CoinName $Currency)) {
+ Add-CoinName -Currency $Currency -CoinName $Request.$_.CoinName
+ }
+
+ $Stat = Set-Stat -Name "$($PoolVariant)_$($Algorithm_Norm)$(If ($Currency) { "-$($Currency)" })_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor) -FaultDetection $false
+
+ ForEach ($Region in $PoolConfig.Region) {
+ $Region_Norm = Get-Region $Region
+
+ [PSCustomObject]@{
+ Name = [String]$PoolVariant
+ BaseName = [String]$Name
+ Algorithm = [String]$Algorithm_Norm
+ Currency = [String]$Currency
+ Price = [Double]$Stat.Live
+ StablePrice = [Double]$Stat.Week
+ Accuracy = [Double](1 - [Math]::Min([Math]::Abs($Stat.Week_Fluctuation), 1))
+ EarningsAdjustmentFactor = [Double]$PoolConfig.EarningsAdjustmentFactor
+ Host = "$($Algorithm).$($Region).$($HostSuffix)"
+ Port = [UInt16]$PoolPort
+ User = [String]$Wallet
+ Pass = "$($PoolConfig.WorkerName),c=$PayoutCurrency"
+ Region = [String]$Region_Norm
+ SSL = $false
+ Fee = [Decimal]$Fee
+ Updated = [DateTime]$Updated
+ Workers = [Int]$Workers
+ }
+ }
+ }
+}
diff --git a/Pools/ZergPool.ps1 b/Pools/ZergPool.ps1
new file mode 100644
index 0000000000..e003fd0350
--- /dev/null
+++ b/Pools/ZergPool.ps1
@@ -0,0 +1,100 @@
+<#
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
+
+
+NemosMiner is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+NemosMiner is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+#>
+
+<#
+Product: NemosMiner
+File: ZergPool.ps1
+Version: 4.0.0.28
+Version date: 24 April 2022
+#>
+
+using module ..\Includes\Include.psm1
+
+param(
+ [PSCustomObject]$Config,
+ [PSCustomObject]$PoolsConfig,
+ [String]$PoolVariant,
+ [Hashtable]$Variables
+)
+
+$Name = (Get-Item $MyInvocation.MyCommand.Path).BaseName
+$PoolConfig = $PoolsConfig.(Get-PoolBaseName $Name)
+$PriceField = $Variables.PoolData.$Name.Variant.$PoolVariant.PriceField
+$DivisorMultiplier = $Variables.PoolData.$Name.Variant.$PoolVariant.DivisorMultiplier
+$PayoutCurrency = $PoolConfig.Wallets.Keys | Select-Object -First 1
+$Regions = If ($Config.UseAnycast -and $PoolConfig.Region -contains "N/A (Anycast)") { "N/A (Anycast)" } Else { $PoolConfig.Region | Where-Object { $_ -ne "N/A (Anycast)" } }
+$Wallet = $PoolConfig.Wallets.$PayoutCurrency
+
+If ($DivisorMultiplier -and $Regions -and $Wallet) {
+
+ $PayoutThreshold = $PoolConfig.PayoutThreshold.$PayoutCurrency
+ If (-not $PayoutThreshold -and $PoolConfig.PayoutThreshold.mBTC) { $PayoutThreshold = $PoolConfig.PayoutThreshold.mBTC / 1000 }
+ $PayoutThresholdParameter = ",pl=$([Double]$PayoutThreshold)"
+
+ Try {
+ $Request = Get-Content ((Split-Path -Parent (Get-Item $MyInvocation.MyCommand.Path).Directory) + "\Brains\$($Name)\$($Name).json") -ErrorAction Stop | ConvertFrom-Json
+ }
+ Catch { Return }
+
+ If (-not $Request) { Return }
+
+ $HostSuffix = "mine.zergpool.com"
+
+ $Request.PSObject.Properties.Name | Where-Object { [Double]$Request.$_.$PriceField -gt 0 } | Where-Object { $Request.$_.noautotrade -ne 1 -or $PayoutCurrency -eq "$($Request.$_.currency)".Trim() } | ForEach-Object {
+ $Algorithm = $Request.$_.name
+ $Algorithm_Norm = Get-Algorithm $Algorithm
+ $Currency = "$($Request.$_.currency)".Trim()
+ $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
+ $Fee = $Request.$_.Fees / 100
+ $PoolPort = $Request.$_.port
+ $Updated = $Request.$_.Updated
+ $Workers = $Request.$_.workers
+
+ # Add coin name
+ If ($Request.$_.CoinName -and $Currency -and -not (Get-CoinName $Currency)) {
+ Add-CoinName -Currency $Currency -CoinName $Request.$_.CoinName
+ }
+
+ $Stat = Set-Stat -Name "$($PoolVariant)_$($Algorithm_Norm)$(If ($Currency) { "-$($Currency)" })_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor) -FaultDetection $false
+
+ ForEach ($Region in $Regions) {
+
+ $PoolHost = If ($Region -eq "N/A (Anycast)") { "$Algorithm.$HostSuffix" } Else { "$Algorithm.$Region.$HostSuffix" }
+
+ [PSCustomObject]@{
+ Name = [String]$PoolVariant
+ BaseName = [String]$Name
+ Algorithm = [String]$Algorithm_Norm
+ Currency = [String]$Currency
+ Price = [Double]$Stat.Live
+ StablePrice = [Double]$Stat.Week
+ Accuracy = [Double](1 - [Math]::Min([Math]::Abs($Stat.Week_Fluctuation), 1))
+ EarningsAdjustmentFactor = [Double]$PoolConfig.EarningsAdjustmentFactor
+ Host = [String]$PoolHost
+ Port = [UInt16]$PoolPort
+ User = [String]$Wallet
+ Pass = "$($PoolConfig.WorkerName),c=$PayoutCurrency$PayoutThresholdParameter"
+ Region = "$(Get-Region $Region)"
+ SSL = $false
+ Fee = [Decimal]$Fee
+ Updated = [DateTime]$Updated
+ Workers = [Int]$Workers
+ }
+ }
+ }
+}
diff --git a/Pools/ahashpool.ps1 b/Pools/ahashpool.ps1
deleted file mode 100644
index 9e320291f1..0000000000
--- a/Pools/ahashpool.ps1
+++ /dev/null
@@ -1,51 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "https://www.ahashpool.com/api/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".mine.ahashpool.com"
-# $PriceField = "actual_last24h"
-$PriceField = "estimate_current"
-$DivisorMultiplier = 1000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = "$ahashpool_Coin $ahashpool_Coinname"
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/ahashpool24hr.ps1 b/Pools/ahashpool24hr.ps1
deleted file mode 100644
index 64717ac0b4..0000000000
--- a/Pools/ahashpool24hr.ps1
+++ /dev/null
@@ -1,51 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "https://www.ahashpool.com/api/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".mine.ahashpool.com"
-$PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
-$DivisorMultiplier = 1000000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = "$ahashpool_Coin $ahashpool_Coinname"
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/ahashpoolplus.ps1 b/Pools/ahashpoolplus.ps1
deleted file mode 100644
index 5bdb4e6bba..0000000000
--- a/Pools/ahashpoolplus.ps1
+++ /dev/null
@@ -1,51 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-Try {
- $Request = get-content ((split-path -parent (get-item $script:MyInvocation.MyCommand.Path).Directory) + "\BrainPlus\ahashpoolplus\ahashpoolplus.json") | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".mine.ahashpool.com"
-$PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
-$DivisorMultiplier = 1000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = "$ahashpool_Coin $ahashpool_Coinname"
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/blazepool.ps1 b/Pools/blazepool.ps1
deleted file mode 100644
index 6c94b7d62b..0000000000
--- a/Pools/blazepool.ps1
+++ /dev/null
@@ -1,51 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "http://api.blazepool.com/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".mine.blazepool.com"
-# $PriceField = "actual_last24h"
-$PriceField = "estimate_current"
-$DivisorMultiplier = 1000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = ""
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/blazepool24hr.ps1 b/Pools/blazepool24hr.ps1
deleted file mode 100644
index 89acc5f30c..0000000000
--- a/Pools/blazepool24hr.ps1
+++ /dev/null
@@ -1,51 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "http://api.blazepool.com/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".mine.blazepool.com"
-$PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
-$DivisorMultiplier = 1000000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = ""
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/blazepoolplus.ps1 b/Pools/blazepoolplus.ps1
deleted file mode 100644
index b9f0c70e7c..0000000000
--- a/Pools/blazepoolplus.ps1
+++ /dev/null
@@ -1,51 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-Try {
- $Request = get-content ((split-path -parent (get-item $script:MyInvocation.MyCommand.Path).Directory) + "\BrainPlus\blazepoolplus\blazepoolplus.json") | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".mine.blazepool.com"
-$PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
-$DivisorMultiplier = 1000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = ""
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/blockmasters.ps1 b/Pools/blockmasters.ps1
deleted file mode 100644
index 44b5e3fd76..0000000000
--- a/Pools/blockmasters.ps1
+++ /dev/null
@@ -1,54 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "http://blockmasters.co/api/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = "blockmasters.co"
-# $PriceField = "actual_last24h"
-$PriceField = "estimate_current"
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = 1000000 * [Double]$Request.$_.mbtc_mh_factor
-
- switch ($PoolAlgorithm) {
- "bcd" {$Divisor /= 10}
- }#temp fix
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = "$ahashpool_Coin $ahashpool_Coinname"
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/blockmasters24hr.ps1 b/Pools/blockmasters24hr.ps1
deleted file mode 100644
index 52de95259f..0000000000
--- a/Pools/blockmasters24hr.ps1
+++ /dev/null
@@ -1,51 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "http://blockmasters.co/api/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = "blockmasters.co"
-$PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
-$DivisorMultiplier = 1000000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = "$ahashpool_Coin $ahashpool_Coinname"
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/blockmastersplus.ps1 b/Pools/blockmastersplus.ps1
deleted file mode 100644
index e9d679fe1d..0000000000
--- a/Pools/blockmastersplus.ps1
+++ /dev/null
@@ -1,63 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-Try {
- $Request = get-content ((split-path -parent (get-item $script:MyInvocation.MyCommand.Path).Directory) + "\BrainPlus\blockmastersplus\blockmastersplus.json") | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = "blockmasters.co"
-$PriceField = "Plus_Price"
-# $PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
-$DivisorMultiplier = 1000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- $Locations = "eu.", ""
- $Locations | ForEach-Object {
- $Pool_Location = $_
-
- switch ($Pool_Location) {
- "eu." {$Location = "EU"}
- "" {$Location = "US"}
- }
- $PoolHost = "$($Pool_Location)$($HostSuffix)"
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = "$ahashpool_Coin $ahashpool_Coinname"
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
- }
-}
diff --git a/Pools/hashrefinery.ps1 b/Pools/hashrefinery.ps1
deleted file mode 100644
index 6033cbadae..0000000000
--- a/Pools/hashrefinery.ps1
+++ /dev/null
@@ -1,51 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "http://pool.hashrefinery.com/api/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".us.hashrefinery.com"
-# $PriceField = "actual_last24h"
-$PriceField = "estimate_current"
-$DivisorMultiplier = 1000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = "$ahashpool_Coin $ahashpool_Coinname"
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/hashrefinery24hr.ps1 b/Pools/hashrefinery24hr.ps1
deleted file mode 100644
index 09433971d7..0000000000
--- a/Pools/hashrefinery24hr.ps1
+++ /dev/null
@@ -1,51 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "http://pool.hashrefinery.com/api/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".us.hashrefinery.com"
-$PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
-$DivisorMultiplier = 1000000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = "$ahashpool_Coin $ahashpool_Coinname"
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/hashrefineryplus.ps1 b/Pools/hashrefineryplus.ps1
deleted file mode 100644
index 1860f62994..0000000000
--- a/Pools/hashrefineryplus.ps1
+++ /dev/null
@@ -1,51 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-Try {
- $Request = get-content ((split-path -parent (get-item $script:MyInvocation.MyCommand.Path).Directory) + "\BrainPlus\hashrefineryplus\hashrefineryplus.json") | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".us.hashrefinery.com"
-$PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
-$DivisorMultiplier = 1000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = "$ahashpool_Coin $ahashpool_Coinname"
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/minemoney.ps1 b/Pools/minemoney.ps1
deleted file mode 100644
index 7ac0282ac8..0000000000
--- a/Pools/minemoney.ps1
+++ /dev/null
@@ -1,60 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "https://www.minemoney.co/api/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".MineMoney.ca"
-# $PriceField = "actual_last24h"
-$PriceField = "estimate_current"
-$DivisorMultiplier = 1000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- $Divisor = 1000000
-
- switch ($PoolAlgorithm) {
- "blake2s" {$Divisor *= 1000}
- "blakecoin" {$Divisor *= 1000}
- "decred" {$Divisor *= 1000}
- "keccak" {$Divisor *= 1000}
- }
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = "$ahashpool_Coin $ahashpool_Coinname"
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/minemoney24hr.ps1 b/Pools/minemoney24hr.ps1
deleted file mode 100644
index 0fcab2ba61..0000000000
--- a/Pools/minemoney24hr.ps1
+++ /dev/null
@@ -1,60 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "https://www.minemoney.co/api/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".MineMoney.ca"
-$PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
-$DivisorMultiplier = 1000000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- $Divisor = 1000000000
-
- switch ($PoolAlgorithm) {
- "blake2s" {$Divisor *= 1000}
- "blakecoin" {$Divisor *= 1000}
- "decred" {$Divisor *= 1000}
- "keccak" {$Divisor *= 1000}
- }
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = "$ahashpool_Coin $ahashpool_Coinname"
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/miningpoolhub.ps1 b/Pools/miningpoolhub.ps1
deleted file mode 100644
index ef0b0c2456..0000000000
--- a/Pools/miningpoolhub.ps1
+++ /dev/null
@@ -1,60 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try { $Request = Invoke-WebRequest "https://miningpoolhub.com/index.php?page=api&action=getautoswitchingandprofitsstatistics" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request.success) {
- return
-}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-$Locations = 'EU', 'US', 'Asia'
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-
- $Request.return | ForEach-Object {
- $Current = $_
- $Algorithm = $_.algo -replace "-"
- $Coin = (Get-Culture).TextInfo.ToTitleCase(($_.current_mining_coin -replace "-", " ")) -replace " "
-
- $Stat = Set-Stat -Name "$($Name)_$($Algorithm)_Profit" -Value ([decimal]$_.profit / 1000000000)
- $Price = (($Stat.Live * (1 - [Math]::Min($Stat.Day_Fluctuation, 1))) + ($Stat.Day * (0 + [Math]::Min($Stat.Day_Fluctuation, 1))))
-
-$Locations | ForEach-Object {
- $Location = $_
-
- [PSCustomObject]@{
- Algorithm = $Algorithm
- Info = $Coin
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- Protocol = 'stratum+tcp'
- Host = $Current.all_host_list.split(";") | Sort-Object -Descending {$Current -ilike "$Location*"} | Select-Object -First 1
- Port = $Current.algo_switch_port
- User = "$($PoolConf.UserName).$($PoolConf.WorkerName.replace('ID=',''))"
- Pass = 'x'
- Location = $Location
- SSL = $false
- }
-
- [PSCustomObject]@{
- Algorithm = $Algorithm
- Info = $Coin
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- Protocol = 'stratum+ssl'
- Host = $Current.all_host_list.split(";") | Sort-Object -Descending {$Current -ilike "$Location*"} | Select-Object -First 1
- Port = $Current.algo_switch_port
- User = "$($PoolConf.UserName).$($PoolConf.WorkerName.replace('ID=',''))"
- Pass = 'x'
- Location = $Location
- SSL = $true
- }
- }
-}
-
-
diff --git a/Pools/nicehash.ps1 b/Pools/nicehash.ps1
deleted file mode 100644
index 024d5dc549..0000000000
--- a/Pools/nicehash.ps1
+++ /dev/null
@@ -1,73 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "https://api.nicehash.com/api?method=simplemultialgo.info" -TimeoutSec 15 -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-
-# Placed here for Perf (Disk reads)
-$ConfName = if ($Config.PoolsConfig.$Name -ne $Null) {$Name}else {"default"}
-$PoolConf = $Config.PoolsConfig.$ConfName
-
-
-$Request.result.simplemultialgo | ForEach-Object {
- $Algo = $_.Name
- $NiceHash_Port = $_.port
- $NiceHash_Algorithm = Get-Algorithm $_.name
- $NiceHash_Coin = ""
-
- $Divisor = 1000000000
-
- $Stat = Set-Stat -Name "$($Name)_$($NiceHash_Algorithm)_Profit" -Value ([Double]$_.paying / $Divisor)
-
- $Locations = "eu", "usa", "hk", "jp", "in", "br"
- $Locations | ForEach-Object {
- $NiceHash_Location = $_
-
- switch ($NiceHash_Location) {
- "eu" {$Location = "EU"}
- "usa" {$Location = "US"}
- "jp" {$Location = "JP"}
- "hk" {$Location = "HK"}
- "in" {$Location = "IN"}
- "br" {$Location = "BR"}
- }
- $NiceHash_Host = "$($Algo).$NiceHash_Location.nicehash.com"
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $NiceHash_Algorithm
- Info = $NiceHash_Coin
- Price = $Stat.Live * $PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $NiceHash_Host
- Port = $NiceHash_Port
- User = "$($PoolConf.Wallet).$($PoolConf.WorkerName.Replace('ID=',''))"
- Pass = "x"
- Location = $Location
- SSL = $false
- }
-
- [PSCustomObject]@{
- Algorithm = $NiceHash_Algorithm
- Info = $NiceHash_Coin
- Price = $Stat.Live * $PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+ssl"
- Host = $NiceHash_Host
- Port = $NiceHash_Port
- User = "$($PoolConf.Wallet).$($PoolConf.WorkerName.Replace('ID=',''))"
- Pass = "x"
- Location = $Location
- SSL = $true
- }
- }
- }
-}
diff --git a/Pools/nlpool.ps1 b/Pools/nlpool.ps1
deleted file mode 100644
index 58d4f3d23d..0000000000
--- a/Pools/nlpool.ps1
+++ /dev/null
@@ -1,55 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "http://www.nlpool.nl/api/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = "mine.nlpool.nl"
-# $PriceField = "actual_last24h"
-$PriceField = "estimate_current"
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
-$ConfName = if ($Config.PoolsConfig.$Name -ne $Null) {$Name}else {"default"}
-$PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = $HostSuffix
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = 1000000 * [Double]$Request.$_.mbtc_mh_factor
-
- switch ($PoolAlgorithm) {
- "Yescrypt" {$Divisor *= 100} #temp fix
-
- }
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = ""
- Price = $Stat.Live * $PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/nlpool24hr.ps1 b/Pools/nlpool24hr.ps1
deleted file mode 100644
index 59d07ebb2c..0000000000
--- a/Pools/nlpool24hr.ps1
+++ /dev/null
@@ -1,55 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "http://www.nlpool.nl/api/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = "mine.nlpool.nl"
-$PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = $HostSuffix
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = 1000000000 * [Double]$Request.$_.mbtc_mh_factor
-
- switch ($PoolAlgorithm) {
- "Yescrypt" {$Divisor *= 100} #temp fix
-
- }
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = ""
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/nlpoolplus.ps1 b/Pools/nlpoolplus.ps1
deleted file mode 100644
index 3f2f726757..0000000000
--- a/Pools/nlpoolplus.ps1
+++ /dev/null
@@ -1,55 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-Try {
- $Request = get-content ((split-path -parent (get-item $script:MyInvocation.MyCommand.Path).Directory) + "\BrainPlus\nlpoolplus\nlpoolplus.json") | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = "mine.nlpool.nl"
-$PriceField = "Plus_Price"
-# $PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = $HostSuffix
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = 1000000 * [Double]$Request.$_.mbtc_mh_factor
-
- switch ($PoolAlgorithm) {
- "Yescrypt" {$Divisor *= 100} #temp fix
-
- }
-
- $Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = ""
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/phiphipool.ps1 b/Pools/phiphipool.ps1
deleted file mode 100644
index a0d0fca21f..0000000000
--- a/Pools/phiphipool.ps1
+++ /dev/null
@@ -1,59 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-RestMethod "http://www.phi-phi-pool.com/api/status" -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".phi-phi-pool.com"
-# $PriceField = "actual_last24h"
-$PriceField = "estimate_current"
-$DivisorMultiplier = 1000000
-
-# Placed here for Perf (Disk reads)
-$ConfName = if ($Config.PoolsConfig.$Name -ne $Null) {$Name}else {"default"}
-$PoolConf = $Config.PoolsConfig.$ConfName
-
-$Locations = "asia", "eu"
-$Locations | ForEach-Object {
- $Pool_Location = $_
-
- switch ($Pool_Location) {
- "eu" {$Location = "EU"} #Europe
- "asia" {$Location = "JP"} #Asia [Thailand]
- default {$Location = "JP"}
- }
-
- $Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($Pool_Location)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
- }
-}
diff --git a/Pools/phiphipool24h.ps1 b/Pools/phiphipool24h.ps1
deleted file mode 100644
index bed2b350b4..0000000000
--- a/Pools/phiphipool24h.ps1
+++ /dev/null
@@ -1,59 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-RestMethod "http://www.phi-phi-pool.com/api/status" -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".phi-phi-pool.com"
-$PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
-$DivisorMultiplier = 1000000000
-
-# Placed here for Perf (Disk reads)
-$ConfName = if ($Config.PoolsConfig.$Name -ne $Null) {$Name}else {"default"}
-$PoolConf = $Config.PoolsConfig.$ConfName
-
-$Locations = "asia", "eu"
-$Locations | ForEach-Object {
- $Pool_Location = $_
-
- switch ($Pool_Location) {
- "eu" {$Location = "EU"} #Europe
- "asia" {$Location = "JP"} #Asia [Thailand]
- default {$Location = "JP"}
- }
-
- $Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($Pool_Location)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
- }
-}
diff --git a/Pools/phiphipool24hr.ps1 b/Pools/phiphipool24hr.ps1
deleted file mode 100644
index bed2b350b4..0000000000
--- a/Pools/phiphipool24hr.ps1
+++ /dev/null
@@ -1,59 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-RestMethod "http://www.phi-phi-pool.com/api/status" -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".phi-phi-pool.com"
-$PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
-$DivisorMultiplier = 1000000000
-
-# Placed here for Perf (Disk reads)
-$ConfName = if ($Config.PoolsConfig.$Name -ne $Null) {$Name}else {"default"}
-$PoolConf = $Config.PoolsConfig.$ConfName
-
-$Locations = "asia", "eu"
-$Locations | ForEach-Object {
- $Pool_Location = $_
-
- switch ($Pool_Location) {
- "eu" {$Location = "EU"} #Europe
- "asia" {$Location = "JP"} #Asia [Thailand]
- default {$Location = "JP"}
- }
-
- $Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($Pool_Location)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
- }
-}
diff --git a/Pools/phiphipoolplus.ps1 b/Pools/phiphipoolplus.ps1
deleted file mode 100644
index 1e3e6700dc..0000000000
--- a/Pools/phiphipoolplus.ps1
+++ /dev/null
@@ -1,60 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-Try {
- $Request = get-content ((split-path -parent (get-item $script:MyInvocation.MyCommand.Path).Directory) + "\BrainPlus\phiphipoolplus\phiphipoolplus.json") | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".phi-phi-pool.com"
-$PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
-$DivisorMultiplier = 1000000
-
-# Placed here for Perf (Disk reads)
-$ConfName = if ($Config.PoolsConfig.$Name -ne $Null) {$Name}else {"default"}
-$PoolConf = $Config.PoolsConfig.$ConfName
-
- $Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
-$Locations = "asia", "eu"
-$Locations | ForEach-Object {
- $Pool_Location = $_
-
- switch ($Pool_Location) {
- "eu" {$Location = "EU"} #Europe
- "asia" {$Location = "JP"} #Asia [Thailand]
- default {$Location = "JP"}
- }
- $PoolHost = "$($Pool_Location)$($HostSuffix)"
-
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
- }
-}
diff --git a/Pools/zergpool.ps1 b/Pools/zergpool.ps1
deleted file mode 100644
index 8072faec10..0000000000
--- a/Pools/zergpool.ps1
+++ /dev/null
@@ -1,51 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "http://api.zergpool.com:8080/api/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".mine.zergpool.com"
-# $PriceField = "actual_last24h_shared"
-$PriceField = "estimate_current"
-$DivisorMultiplier = 1000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
-$ConfName = if ($Config.PoolsConfig.$Name -ne $Null) {$Name}else {"default"}
-$PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = ""
- Price = $Stat.Live * $PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/zergpool24hr.ps1 b/Pools/zergpool24hr.ps1
deleted file mode 100644
index 89ec23dbc8..0000000000
--- a/Pools/zergpool24hr.ps1
+++ /dev/null
@@ -1,51 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "http://api.zergpool.com:8080/api/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".mine.zergpool.com"
-$PriceField = "actual_last24h_shared"
-# $PriceField = "estimate_current"
-$DivisorMultiplier = 1000000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
-$ConfName = if ($Config.PoolsConfig.$Name -ne $Null) {$Name}else {"default"}
-$PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = ""
- Price = $Stat.Live * $PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/zergpoolplus.ps1 b/Pools/zergpoolplus.ps1
deleted file mode 100644
index 6ccd1ab7d0..0000000000
--- a/Pools/zergpoolplus.ps1
+++ /dev/null
@@ -1,51 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1; RegisterLoaded(".\Include.ps1")}
-
-Try {
- $Request = get-content ((split-path -parent (get-item $script:MyInvocation.MyCommand.Path).Directory) + "\BrainPlus\zergpoolplus\zergpoolplus.json") | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".mine.zergpool.com"
- $PriceField = "Plus_Price"
-# $PriceField = "actual_last24h_shared"
-# $PriceField = "estimate_current"
- $DivisorMultiplier = 1000000
-
-$Location = "US"
-
-# Placed here for Perf (Disk reads)
-$ConfName = if ($Config.PoolsConfig.$Name -ne $Null) {$Name}else {"default"}
-$PoolConf = $Config.PoolsConfig.$ConfName
-
-$Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- $Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = ""
- Price = $Stat.Live * $PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
-}
diff --git a/Pools/zpool.ps1 b/Pools/zpool.ps1
deleted file mode 100644
index 1d06ce33cc..0000000000
--- a/Pools/zpool.ps1
+++ /dev/null
@@ -1,63 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "http://www.zpool.ca/api/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".mine.zpool.ca"
-# $PriceField = "actual_last24h"
-$PriceField = "estimate_current"
-$DivisorMultiplier = 1000000
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-
- $Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = $_
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- $Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- $Locations = "eu", "na", "sea"
- $Locations | ForEach-Object {
- $Pool_Location = $_
-
- switch ($Pool_Location) {
- "eu" {$Location = "EU"}
- "na" {$Location = "US"}
- "sea" {$Location = "JP"}
- default {$Location = "US"}
- }
- $PoolHost = "$($Algo).$($Pool_Location)$($HostSuffix)"
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = "$ahashpool_Coin $ahashpool_Coinname"
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Pools/zpool24hr.ps1 b/Pools/zpool24hr.ps1
deleted file mode 100644
index 5528572852..0000000000
--- a/Pools/zpool24hr.ps1
+++ /dev/null
@@ -1,64 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-try {
- $Request = Invoke-WebRequest "http://www.zpool.ca/api/status" -UseBasicParsing -Headers @{"Cache-Control" = "no-cache"} | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".mine.zpool.ca"
-$PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
-$DivisorMultiplier = 1000000000
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-
- $Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = $_
- $PoolHost = "$($_)$($HostSuffix)"
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- if ((Get-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit") -eq $null) {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
- else {$Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))}
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- $Locations = "eu", "na", "sea"
- $Locations | ForEach-Object {
- $Pool_Location = $_
-
- switch ($Pool_Location) {
- "eu" {$Location = "EU"}
- "na" {$Location = "US"}
- "sea" {$Location = "JP"}
- default {$Location = "US"}
- }
- $PoolHost = "$($Algo).$($Pool_Location)$($HostSuffix)"
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = "$ahashpool_Coin $ahashpool_Coinname"
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
- }
-}
diff --git a/Pools/zpoolplus.ps1 b/Pools/zpoolplus.ps1
deleted file mode 100644
index 01ac7e8574..0000000000
--- a/Pools/zpoolplus.ps1
+++ /dev/null
@@ -1,62 +0,0 @@
-if (!(IsLoaded(".\Include.ps1"))) {. .\Include.ps1;RegisterLoaded(".\Include.ps1")}
-
-Try {
- $Request = get-content ((split-path -parent (get-item $script:MyInvocation.MyCommand.Path).Directory) + "\BrainPlus\zpoolplus\zpoolplus.json") | ConvertFrom-Json
-}
-catch { return }
-
-if (-not $Request) {return}
-
-$Name = (Get-Item $script:MyInvocation.MyCommand.Path).BaseName
-$HostSuffix = ".mine.zpool.ca"
- $PriceField = "Plus_Price"
-# $PriceField = "actual_last24h"
-# $PriceField = "estimate_current"
- $DivisorMultiplier = 1000000
-
-# Placed here for Perf (Disk reads)
- $ConfName = if ($Config.PoolsConfig.$Name -ne $Null){$Name}else{"default"}
- $PoolConf = $Config.PoolsConfig.$ConfName
-
-
- $Request | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
- $Algo = $_
- $PoolPort = $Request.$_.port
- $PoolAlgorithm = Get-Algorithm $Request.$_.name
-
- $Divisor = $DivisorMultiplier * [Double]$Request.$_.mbtc_mh_factor
-
- $Stat = Set-Stat -Name "$($Name)_$($PoolAlgorithm)_Profit" -Value ([Double]$Request.$_.$PriceField / $Divisor * (1 - ($Request.$_.fees / 100)))
-
- $PwdCurr = if ($PoolConf.PwdCurrency) {$PoolConf.PwdCurrency}else {$Config.Passwordcurrency}
- $WorkerName = If ($PoolConf.WorkerName -like "ID=*") {$PoolConf.WorkerName} else {"ID=$($PoolConf.WorkerName)"}
-
- $Locations = "eu", "na", "sea"
- $Locations | ForEach-Object {
- $Pool_Location = $_
- switch ($Pool_Location) {
- "eu" {$Location = "EU"}
- "na" {$Location = "US"}
- "sea" {$Location = "JP"}
- default {$Location = "US"}
- }
- $PoolHost = "$($Algo).$($Pool_Location)$($HostSuffix)"
-
- if ($PoolConf.Wallet) {
- [PSCustomObject]@{
- Algorithm = $PoolAlgorithm
- Info = "$ahashpool_Coin $ahashpool_Coinname"
- Price = $Stat.Live*$PoolConf.PricePenaltyFactor
- StablePrice = $Stat.Week
- MarginOfError = $Stat.Week_Fluctuation
- Protocol = "stratum+tcp"
- Host = $PoolHost
- Port = $PoolPort
- User = $PoolConf.Wallet
- Pass = "$($WorkerName),c=$($PwdCurr)"
- Location = $Location
- SSL = $false
- }
- }
- }
-}
diff --git a/README.md b/README.md
index eefd709838..12d8b209ef 100644
--- a/README.md
+++ b/README.md
@@ -1,236 +1,294 @@
# NemosMiner
-Updated 17 May 2019
+NemosMiner monitors mining pools in real-time in order to find the most profitable Algo
-[](https://github.com/nemosminer/Nemosminer/releases)
-[](https://github.com/nemosminer/Nemosminer/releases)
-[](https://github.com/nemosminer/Nemosminer/releases)
-[](https://github.com/nemosminer/Nemosminer/blob/master/LICENSE)
-[](https://github.com/nemosminer/Nemosminer/stargazers)
-[](https://github.com/nemosminer/Nemosminer/network)
+Updated 31 March 2022
-Copyright (c) 2018-2019 Nemo and MrPlus
+
+Copyright (c) 2018-2022 Nemo, MrPlus & UselessGuru
This is free software, and you are welcome to redistribute it
under certain conditions.
-https://github.com/nemosminer/NemosMiner/blob/master/LICENSE
+https://github.com/Minerx117/NemosMiner/blob/master/LICENSE
-by Nemo/Minerx117
+Updated/Maintained by Nemo/Minerx117 & UselessGuru
-with Help From MrPlusGH and grantemsley
-
-[](https://discord.gg/2BCqPxe) [Click to Join Discord](https://discord.gg/2BCqPxe)
+with a lot of help from MrPlusGH, grantemsley & UselessGuru. Without them NemosMiner would not be possible.
-*****
-**Have questions? Need help?** We're on Discord: https://discord.gg/2BCqPxe
+NemosMiner code is partly based on
+
+- MultiPoolMiner which can be found here: https://github.com/MultiPoolMiner/MultiPoolMiner (Project is no longer maintained)
-NemosMiner Monitors mining pools in real-time in order to find the most profitable Algo
+- NPlusMiner which can be found here: https://github.com/MrPlusGH/NPlusMiner
- GUI and easy configuration
- Auto Benchmarks Each algo to get optimal speeds
- Fully automated
- Auto Downloads Miners
- Auto Updates
- Monitoring
+
+Note: NemosMiner Version 4.x is **NOT backwards compatible** with the 3.8.x code base.
+It is highly recommended to install this version to a new directory.
+
+Some configuration options have changed. See 'Changed Config Items.txt' for more information.
+NemosMiner will automatically convert an existing configuration file.
+
+*****
+
+**Main features:**
+ - GUI and easy configuration
+ - Auto Benchmarks each algo to get optimal speeds
+ - Fully automated
+ - Auto Downloads Miners
+ - Auto Updates
+ - Monitoring
+ - Earnings graph
*****
Easy configuration, easy start:
Run NemosMiner.bat
- 1. Config tab
- 2. Set your Wallet address and Username
- 3. Select your pool
+ 1. Edit configuration (http://localhost:3999/configedit.html)
+ 2. Set your Wallet address(es) and Username(s)
+ 3. Select your pool(s)
4. Save Config
5. Start
-
- note: 2. you only need to change Username if you are using Miningpoolhub
-
- Algo selection / removal
-
- +algo for algo selection
- -algo for algo removal
- If "+" Used, all selected algo have to be listed
- If "Minus" Used, all algo selected but exluded ones.
+ Note: 2. you only need to change Username if you are using Miningpoolhub or ProHashing
+
+ Algorithm selection / removal
+
+ +[algorithm] to enable algorithm
+ -[algorithm] to disable algorithm
+
+ If '+' is used, then only the explicitly enabled algorithms are used
+ If '-' is used, then all algorithms except the disabled ones are used
+ Leave empty to use ALL available algorithms (not recommended as it may cause more miner switching)
Do not combine + and - for the same algo
- Examples:
- Algo list = -x16r
- Will mine anything but x16r
+ Examples:
+ Algorithm list = -x16r
+ Will mine anything but x16r
- Algo list = -x16r,-bcd
- Will mine anything but x16r and bcd
+ Algorithm list = -x16r,-bcd
+ Will mine anything but x16r and bcd
- Algo list = +x16r
- Will mine only x16r
+ Algorithm list = +x16r
+ Will mine only x16r
- Algo list = +x16r,+bcd
- Will mine only x16r and BCD
+ Algorithm list = +x16r,+bcd
+ Will mine only x16r and BCD
- Algo list blank
- Will mine anything
-
- Pools variants
+ Algorithm list blank
+ Will mine anything
- 24hr - uses last 24hour Actual API too request profit
- -Low switching rate
- plus - uses advanced calculations to reduce switching
- -Medium switching rate
- normal - uses current estimate API too request profit
- -High switching rate
-
- Developer/Contributors Donation:
- list and wallets is publicly available at: https://nemosminer.com/data/devlist.json
-
- There is a 5 minute per day donation (0.3%), that can be changed in the config (Minimum is 3)0.2%
- We want to stay completely transparent on the way donations are managed in the product. Donations occurs once every 24 hours for the selected amount of time (default 5 minutes). The first donation sequence occurs 1 hour after miners are started. If Interval is set higher than the donation time, the interval will prime. Example for default parameters. Miners started at 10, First donation cycle runs at 10:55 untill 11, Next donation cycle occurs 24 hours after.All donation time and addresses are recording in the logs folder.
+ Pools Variants
-NemosMiner Monitoring Server : https://nemosminer.com
+ *24hr - uses last 24hour price data in pool API to calculate profit (no estimates or advanced calculations)
- Keep tabs on all your mining rigs from one place
- You can now optionally monitor all your workers remotely, both in the GUI and via https://nemosminer.com
- Monitoring setup instructions https://nemosminer.com/setup.php
+ *Plus - uses advanced calculations to reduce uneeded switching
+
+ normal - uses current price data in pool API to calculate profit (no estimates or advanced calculations)
+
+ *Coins - uses advanced calculations, mines only top paying coin in Algo (MiningPoolHub & ZergPool)
+
+
+ Developer/Contributors Donation:
+ The list and wallets is stored in [NemosMiner Directory]\Data\DonationData.json
+
+ Donation Fee = 0.9%
+ There is 13 minute per day default donation (0.9%),
+ which can be increased or decreased in the configuration editor.
+ Please help support the great team behind NemosMiner by leaving mining donations turned on.
+ We want to stay completely transparent on the way fees are managed in the product.
+ Donation cycle occurs once in 24hrs (or once until midnight if NemosMiner has been running less than 24hrs).
+ Donation start time is randomized each time.
+ It will then mine for one randomly chosen developer / contributor for the configured duration.
+
+ Example for default parameters (13 minutes):
+ - NemosMiner was started at 10:00h
+ - First donation cycle starts somewhen beween 10:01h and 23:47h and will then donate for 13 minutes, then mine for you again until the next donation run.
+ - After 00:00h the donation start time is randomized again.
+ - When donation start time is reached it will then donate for 13 minutes, then mine for you again until the next donation run.
+ All donation time and addresses are recorded in the logs files.
+
+ NemosMiner Monitoring Server: https://nemosminer.com
+
+ Keep tabs on all your mining rigs from one place
+ You can now optionally monitor all your workers remotely, both in the GUI and via https://nemosminer.com
+ Monitoring setup instructions https://nemosminer.com/setup.php
-
GUI
-
- Since version 3.0 NemosMiner has a GUI making it easy to configure and run.
- Relies on config files. No need to edit bat files. Simply run NemosMiner
- Set the config on the config tab, save, close, run
+
+ Since version 3.9.9.x (Beta) NemosMiner has a Web GUI making it easy to configure and run.
+ NemosMiner relies on config files. No need to edit bat files. Simply run NemosMiner.bat
+ Set the config in the Web GUI (http://localhost:3999/configedit.html), apply & start mining
Pause mining
-
+
Ability to pause miners while keeping other jobs running (pause button)
This will stop mining activity
BrainPlus will still run in the background avoiding the learning phase on resume
- EarningTracker will still run in the background avoiding the learning phase on resume
-
- prerun
-
- Ability to run a batch prior switching to a specific algo.
- For example, can be used to set per algo OC via nvidiaInspector
- Simply create a file named .bat in prerun folder
- If .bat does not exist, will try to launch prerun/default.bat
+ EarningTracker will still run in the background to keep the pool balances up to date
+
+ PreRun
+
+ Ability to run a batch prior switching to a specific miner and/or algorithm.
+ The prerun scripts can be used to set per miner/algorithm OC via nvidiaInspector or OverdriveNTool.
+ Before starting a miner executable NemosMiner is trying to launch one of the following 3 prerun scripts (in this order):
+ 1. _.bat
+ Simply create a file named _.bat in prerun folder, e.g. 'Bminer-v16.4.11-1xRadeonRX5808GB-Handshake-10.bat' or 'CcminerMTP-v1.3.2-1xGTX10606GB_MTP.bat'
+ 2. .bat
+ Simply create a file named .bat in prerun folder, e.g. 'Ethash.bat'
+ 3. default.bat
+ If neither of the two above exist, NemosMiner will try to launch prerun\default.bat
Use overclock with caution
- Per pools config (Advanced)
-
- - **This is for advanced users. Do not use if you do not know what you are doing.**
- - You can now set specific options per pool. For example, you can mine NiceHash on the internal wallet and other pools on a valid wallet. This configuration is provided as an example in Config\PoolsConfig-NHInternal.json
- - Available options
- - Wallet = your wallet address
- - UserName = your MPH user name
- - WorkerName = your worker name
- - PricePenaltyFactor = See explanation below
- - Algorithm = List of included or excluded Aglo on pool (see example files)
- - Usage
- - The file Config\PoolsConfig.json contains per pool configuration details. If a pool is listed in this file,
- the specific settings will be taken into account. If not, the setting for the entry name default will be used.
- **Do not delete the default entry.**
- - Edit Config\PoolsConfig.json
- - Add an entry for the pool you want to customize
- - The name must be the NemosMiner name for the pool. ie. for ahashpool, if you use Plus. The name is ahashpoolplus.
- - (**careful with json formating ;)**)
- - Best way is to duplicate the default entry
- - Note that the GUI only updates the default entry. Any other changes need to be done manualy
+ Per pool config (Advanced)
+
+ **This is for advanced users. Do not use if you do not know what you are doing.**
+
+ The file Config\PoolsConfig.json contains configuration details for the pools.
+ A separate section can be added for each pool base name. If a pool is listed in this file,
+ the specific settings will be taken into account. If not, the built in default values will be used.
+ See \Data\PoolData.json for the basic structure of the file Config\PoolsConfig.json
+
+ You can set specific options per pool. For example, you can mine NiceHash on the internal wallet and other pools on a valid wallet. This configuration is provided as an example in Config\PoolsConfig-NHInternal.json
+
+ Available options:
+ - Wallets[Currency] = Your wallet address for [Currency]; some pools, e.g. HiveOn require wallets in each supported currency
+ - UserName = your MPH or ProHashing user name
+ - WorkerName = your worker name
+ - PricePenaltyFactor = See explanation below
+ - Algorithm = List of included or excluded algorithms per pool (see example files)
+ - PayoutThreshold[Currency] = pool will allow pyout if this amount is reached
+
+ Usage:
+ - Edit Config\PoolsConfig.json
+ - Add an entry for the pool you want to customize
+ - The name must be the pool base name (omit *24hrs or *Coins), e.g ZergPool (even if you have configured ZergPoolCoins in the pool list)
+ - (**careful with json formating ;)**
+
+ Note that the GUI only updates default values (valid for ALL pools unless there is pool specific configuration setting defined in 'Config\PoolConfig.json'). Any other changes need to be done manually.
PricePenaltyFactor
- - When using advanced per pool configuration, it is possible to add a penalty factor for a specific pool. This simply adds as a multiplicator on estimations presented by the pool.
- - Example scenario
- - NiceHash has a 4% fee - Set PricePenaltyFactor to 0.96 (1-0.04)
- - You feel like a pool is exaggerating his estimations by 10% - Set PricePenaltyFactor to 0.9
+ When using advanced per pool configuration, it is possible to add a penalty factor for a specific pool. This simply adds a multiplicator on estimations presented by the pool.
+
+ Example scenario:
+ - You feel like a pool is exaggerating its estimations by 10% - Set PricePenaltyFactor to 0.9
- zergpoolplus/nlpoolplus/ahashpoolplus/zpoolplus/blazepoolplus/phiphipoolplus/blockmastersplus/hashrefineryplus
-
- Uses calculations based on 24hractual and currentestimate ahashpool prices to get more realistic estimate.
- Includes some trust index based on past 1hr currentestimate variation from 24hr.
+ Pool Variants
+
+ Poolnames ending in *Plus
+
+ Uses calculations based on 24hr actual and current estimate prices to get a more realistic estimate.
+ Includes some trust index based on past 1hr current estimate variation from 24hr.
AND is NOT sensible to spikes.
- This shows less switching than following Current Estimate and more switching that following the 24hr Actual.
+ This shows less switching than following current estimate and more switching that following the 24hr actual.
Better profitability.
- Earnings Tracking
-
- Displays BTC/H and BTC/D as well a estimation of when the pool payment threshold will be reached.
+ Balances Tracking
+
+ Displays BTC/h and BTC/d and an estimation of when the pool payment threshold will be reached.
Supported pools:
- ahashpool
- zpool
- nicehash
- miningpoolhub (partial)
- If mining more that one pools, shows stats for any supported pool
- Press key e in the console window to show/hide earnings
-
- Support running multiple instances
-
+ - AHashPool
+ - BlockMasters
+ - HiveON
+ - MiningPoolHub
+ - NiceHash (internal & external wallet)
+ - NLPool
+ - ProHashing
+ - ZergPool
+ - Zpool
+ If mining more than one pool, NemosMiner shows stats for all supported pools.
+ Press key 'b' in the console window to show/hide earnings.
+
+ Support for running multiple instances (not recommended)
+
**Experimental**
More than one instance of NemosMiner can run on the same rig
- Each instance must be placed in it's own directory
+ Each instance must be placed in its own directory
Miner has to be started prior the launch of the next instance
- Optional miners (Advanced)
-
- Some miners are not enabled by default in NemosMiner for a variety of reasons:
-
- These are closed source and therefore not enabled in NemosMiner by default.
- Use at your own risk.
-
- For advanced users, check the Optional Miners checkbox on the Config tab to enable these miners.
-
CustomMiners (Advanced)
-
- Users can place any miner.ps1 from miners/optionalminers or custom user created miner.ps1 files, in CustomMiners folder
- leaving miners and optionalminers disabled in config will enable CustomMiners folder
- Algo switching log
-
- Simple algo switching log in csv switching.log file found in Logs folder.
+ Users can place any miner.ps1 from miners/optionalminers or custom user created miner.ps1 files in CustomMiners folder
+ Note: Miners in CustomMiners folder are always enabled (to disable a custom miner it must be removed from the CustomMiners folder)
+
+ Algorithm switching log
+
+ Simple algo switching log as csv (switching.log file found in Logs folder).
You can easily track switching rate.
Console Display Options
-
+
Use -UIStyle Light or -UIStyle Full in config.json
- Full = Usual display (Default)
- Light = Show only currently mining info
- UIStyle automaticaly swtiches to Full during benchmarking.
-
- In session console display toggle
-
- Press key s in the window to switch between light and full display
- Press key e in the window to show/hide earnings
+ Full = Usual display (Default)
+ Light = Show only current mining info
+ UIStyle automatically switches to Full during benchmarking.
+ Press key 's' in the console window to switch UIStyle.
+
+ In session console the following keys are supported
+
+ a: Toggle Accuracy column
+ b: Toggle Pool Balances
+ c: Toggle Cost column
+ e: Toggle Earnings column
+ i: Toggle Earning Bias column
+ l: Toggle listing all available miners
+ m: Toggle Miner Fees column
+ n: Toggle Coin Name column
+ p: Toggle Pool Fees column
+ r: Toggle Profit Bias column
+ s: Toggle Style (full or light)
+ t: Toggle Profit column
+ u: Toggle Power Usage column
+ y: Toggle Currency column
Will toggle display at next refresh
- New version notification
-
+ New version notification (Available since version 3.9.9.10)
+
NemosMiner will notify new version availability
-*****
-
-If you have Windows 7, 8, or 8.1, please update PowerShell:
-[update PowerShell](https://www.microsoft.com/en-us/download/details.aspx?id=54616)
-some miners may need 'Visual C++ 2015' if you don't already have it: (install both x86 & x64)
-[Visual C++ Redistributable for Visual Studio 2015/2014](https://www.microsoft.com/en-US/download/details.aspx?id=48145)
+***Requirements***
+
+PowerShell Version 7.x is required:
+
+[Download Installer for version 7.2.3](https://github.com/PowerShell/PowerShell/releases/download/v7.2.3/PowerShell-7.2.3-win-x64.msi)
-some miners may need 'Visual C++ 2013' if you don't already have it: (install both x86 & x64)
-[Visual C++ Redistributable for Visual Studio 2013/2012](https://www.microsoft.com/en-US/download/details.aspx?id=40784)
+**Some miners may need 'Visual C+ RunTimes download/extract, run install_all.bat file**
-running multiple cards its recommended to increase Virtual Memory 64gb is optimal
+[Visual C+ RunTimes](https://github.com/Minerx117/Visual-C-Runtimes-All-in-One-Sep-2019/releases/download/sep2019/Visual-C-Runtimes-All-in-One-Sep-2019.zip)
-recommended/optimal Windows Nvidia driver 430.39
+**Virtual memory settings**
-[Windows10](http://us.download.nvidia.com/Windows/430.39/430.39-desktop-win10-64bit-international-whql.exe)
+When running multiple cards its recommended to increase Virtual Memory. 64GB is optimal.
-[Windows7, 8, 8.1](http://us.download.nvidia.com/Windows/430.39/430.39-desktop-win8-win7-64bit-international-whql.exe)
+**Recommended/optimal Windows Nvidia driver**
-recommended/optimal Linux Nvidia driver 430.09
+[recommended/optimal Windows Nvidia driver 512.15](https://us.download.nvidia.com/Windows/512.15/512.15-notebook-win10-win11-64bit-international-dch-whql.exe)
-[Linux/Hiveos](http://us.download.nvidia.com/XFree86/Linux-x86_64/430.09/NVIDIA-Linux-x86_64-430.09.run)
+**Recommended/optimal Windows AMD driver**
-Made for & Tested with 6x1070 6x1070ti 6x1080 6x1080ti 6x1660ti 6x2060 6x2070 6x2080 6x2080ti(users have reported up to 12cards working have not tested myself)
-Some miners do not support more that 9 cards
+[Windows 10 AMD GPU Driver 22.2.2](https://www.amd.com/en/support)
+
+ NemosMiner is currently tested on the following Rigs:
+
+ windows10-1xGTX-1660Super/RYZEN-3700x (Test PC)
+
+ windows10-7xAMD-6700XT/Octominer (test Rig 1)
+ windows10-6xRTX-3070/RYZEN-3700x (test Rig 2)
+ windows10-6xRTX-3060ti/RYZEN-3700x (test Rig 3)
+ windows10-1xGTX-1060Super/1xGTX750Ti-2GB/1xRX580-8GB/RX5700/Inteli5-8600K (test Rig 4)
+ windows10-7xAMD-6600XT/Octominer (test Rig 5)
+ (users have reported up to 12cards are working, I have not tested myself)
+ Some miners do not support more than 9 cards
+
+ CPU miners are tested with AMD Ryzen 3700x & Inteli5-8600K CPUs
*****
Licensed under the GNU General Public License v3.0
-Permissions of this strong copyleft license are conditioned on making available complete source code of licensed works and modifications, which include larger works using a licensed work, under the same license. Copyright and license notices must be preserved. Contributors provide an express grant of patent rights. https://github.com/nemosminer/NemosMiner/blob/master/LICENSE
+Permissions of this strong copyleft license are conditioned on making available complete source code of licensed works and modifications, which include larger works using a licensed work, under the same license.
+Copyright and license notices must be preserved. Contributors provide an express grant of patent rights.
+https://github.com/Minerx117/NemosMiner/blob/master/LICENSE
+
+Happy Mining
diff --git a/ResetBenchmark.bat b/ResetBenchmark.bat
deleted file mode 100644
index b0b67a7829..0000000000
--- a/ResetBenchmark.bat
+++ /dev/null
@@ -1 +0,0 @@
-del "Stats\*_HashRate.txt"
diff --git a/ResetProfit.bat b/ResetProfit.bat
deleted file mode 100644
index 8a88bf6ffa..0000000000
--- a/ResetProfit.bat
+++ /dev/null
@@ -1 +0,0 @@
-del "Stats\*Profit.txt"
diff --git a/SupportedPools.txt b/SupportedPools.txt
deleted file mode 100644
index 3888cd6d35..0000000000
--- a/SupportedPools.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-zpool
-hashrefinery
-ahashpool
-miningpoolhub
-nicehash
-zergpool
-minemoney
-blazepool
-phiphipool
-blockmasters
-nlpool
-zergpool
diff --git a/Utils/7z.dll b/Utils/7z.dll
new file mode 100644
index 0000000000..5224967f84
Binary files /dev/null and b/Utils/7z.dll differ
diff --git a/Utils/7z.exe b/Utils/7z.exe
new file mode 100644
index 0000000000..b92ec648e4
Binary files /dev/null and b/Utils/7z.exe differ
diff --git a/Utils/AMD.Memory.Tweak.XL.exe b/Utils/AMD.Memory.Tweak.XL.exe
new file mode 100644
index 0000000000..1855e85f54
Binary files /dev/null and b/Utils/AMD.Memory.Tweak.XL.exe differ
diff --git a/Utils/CheckPreReqs.ps1 b/Utils/CheckPreReqs.ps1
new file mode 100644
index 0000000000..38dcad4c1c
--- /dev/null
+++ b/Utils/CheckPreReqs.ps1
@@ -0,0 +1,51 @@
+. ..\includes\include.ps1
+
+Write-Host "System Version: $([System.Environment]::OSVersion.Version)"
+Write-Host "Powershell version: $($PSVersionTable.PSVersion)"
+
+$VCR2013x86 = Get-WmiObject Win32_Product -Filter "Name LIKE '%Microsoft Visual C++ 2013 x86%'"
+$VCR2013x64 = Get-WmiObject Win32_Product -Filter "Name LIKE '%Microsoft Visual C++ 2013 x64%'"
+
+$VCR2015x86 = Get-WmiObject Win32_Product -Filter "Name LIKE '%Microsoft Visual C++ 2015 x86%'"
+$VCR2015x64 = Get-WmiObject Win32_Product -Filter "Name LIKE '%Microsoft Visual C++ 2015 x64%'"
+
+If ($VCR2013x86.count -lt 1) {
+ Write-Host -F Red "FAILED - Microsoft Visual C++ 2013 x86"
+ Write-Host -F Yellow " Please install from: https://www.microsoft.com/en-gb/download/details.aspx?id=40784"
+}
+else {
+ Write-Host -F Green "OK - Microsoft Visual C++ 2013 x86"
+}
+
+If ($VCR2013x64.count -lt 1) {
+ Write-Host -F Red "FAILED - Microsoft Visual C++ 2013 x64"
+ Write-Host -F Yellow " Please install from: https://www.microsoft.com/en-gb/download/details.aspx?id=40784"
+}
+else {
+ Write-Host -F Green "OK - Microsoft Visual C++ 2013 x64"
+}
+
+If ($VCR2015x86.count -lt 1) {
+ Write-Host -F Red "FAILED - Microsoft Visual C++ 2015 x86"
+ Write-Host -F Yellow " Please install from: https://www.microsoft.com/en-us/download/details.aspx?id=48145"
+}
+else {
+ Write-Host -F Green "OK - Microsoft Visual C++ 2015 x86"
+}
+
+If ($VCR2015x64.count -lt 1) {
+ Write-Host -F Red "FAILED - Microsoft Visual C++ 2015 x64"
+ Write-Host -F Yellow " Please install from: https://www.microsoft.com/en-us/download/details.aspx?id=48145"
+}
+else {
+ Write-Host -F Green "OK - Microsoft Visual C++ 2015 x64"
+}
+
+if ([version](GetNVIDIADriverVersion) -lt [version]"416.34") {
+ Write-Host -F Red "Please update NVIDIA drivers"
+}
+else {
+ Write-Host -F Green "OK - NVIDIA driver version. $([version](GetNVIDIADriverVersion))"
+}
+
+Pause
diff --git a/Utils/HugePages/EnableHugePages.bat b/Utils/HugePages/EnableHugePages.bat
new file mode 100644
index 0000000000..0337f08f9d
--- /dev/null
+++ b/Utils/HugePages/EnableHugePages.bat
@@ -0,0 +1,28 @@
+@echo off
+:: BatchGotAdmin
+::-------------------------------------
+REM --> Check for permissions
+>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
+
+REM --> If error flag set, we do not have admin.
+if '%errorlevel%' NEQ '0' (
+ echo Requesting administrative privileges...
+ goto UACPrompt
+) else ( goto gotAdmin )
+
+:UACPrompt
+ echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
+ set params = %*:"="
+ echo UAC.ShellExecute "cmd.exe", "/c %~s0 %params%", "", "runas", 1 >> "%temp%\getadmin.vbs"
+
+ "%temp%\getadmin.vbs"
+ del "%temp%\getadmin.vbs"
+ exit /B
+
+:gotAdmin
+ pushd "%CD%"
+ CD /D "%~dp0"
+::--------------------------------------
+
+ntrights.exe ntrights +r SeLockMemoryPrivilege -u username
+pause
\ No newline at end of file
diff --git a/Utils/HugePages/help.txt b/Utils/HugePages/help.txt
new file mode 100644
index 0000000000..ad34a0f483
--- /dev/null
+++ b/Utils/HugePages/help.txt
@@ -0,0 +1,5 @@
+change -u username
+
+to your username you want to give access to lock memory privilege/huge page files
+
+eg ntrights.exe ntrights +r SeLockMemoryPrivilege -u bobslaptop
\ No newline at end of file
diff --git a/Utils/HugePages/ntrights.exe b/Utils/HugePages/ntrights.exe
new file mode 100644
index 0000000000..bd5438ea55
Binary files /dev/null and b/Utils/HugePages/ntrights.exe differ
diff --git a/Utils/IOMap.sys b/Utils/IOMap.sys
new file mode 100644
index 0000000000..2c7b3558e8
Binary files /dev/null and b/Utils/IOMap.sys differ
diff --git a/Utils/IOMap64.sys b/Utils/IOMap64.sys
new file mode 100644
index 0000000000..12e3176301
Binary files /dev/null and b/Utils/IOMap64.sys differ
diff --git a/Utils/Monitor/Monitor_1card.bat b/Utils/Monitor/Monitor_1card.bat
new file mode 100644
index 0000000000..cc832b5eb9
--- /dev/null
+++ b/Utils/Monitor/Monitor_1card.bat
@@ -0,0 +1,84 @@
+@echo off
+mode con cols=50 lines=10
+cls
+:begin
+FOR /L %%A IN (60,-1,0) DO (
+ cls
+ echo Timeout [92;1m%%A[0m seconds...
+ timeout /t 1 >nul
+)
+:start
+cls
+:measure
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+set /a total=%gpu_usage0%+%gpu_usage1%
+set /a gpu_average=%total%/1
+
+:end_for
+cls
+echo Average Usage of *1 GPUs usage is %gpu_average%%%
+if %gpu_average% GTR 40 (
+ echo [92;1mMining is working[0m
+ echo [102;92;1mMining is working[0m
+ timeout /t 120 >nul
+ goto :start
+)
+
+set log_file=mining_problems_log.txt
+set ping_time=900
+FOR /F "skip=8 tokens=10" %%G in ('ping -n 3 google.com') DO set ping_time=%%G
+if %ping_time% GTR 0 (
+
+ echo Control checking of GPUs usage, timeout 120 sec...
+ timeout /t 120 >nul
+ goto:recheck
+ :endrecheck
+ if %gpu_average% GTR 40 (
+ echo ------------------- %date% %time% reboot warning>> %log_file%
+ goto :start
+ )
+ echo.
+ echo Average Usage of *1 GPUs usage is [93m%gpu_average%%%[0m
+ echo.
+
+ echo ping is [92m%ping_time%[0m - OK, not internet problem
+ timeout /t 120 >nul
+ goto :endif
+)
+:else
+ cls
+ echo %date% %time% No internet connection>> %log_file%
+ echo No internet connection, keep working...
+ timeout /t 120 >nul
+ goto :begin
+:endif
+
+SET mypath=%~dp0
+SET scrpath=%mypath%Scr
+if not exist "%scrpath%" mkdir "%scrpath%"
+
+rem "%mypath%nircmd.exe" savescreenshot "%scrpath%\%TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+echo "%scrpath%%DATE:~6,4%.%DATE:~3,2%.%DATE:~0,2% %TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+echo PC was restarted at %date% %time%>> %log_file%, mining issue. GPUs usage is %gpu_average%%%
+"nvidia-smi">> %log_file%
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+
+echo [101;93mMining is NOT working, rebooting in 10 seconds...[0m
+timeout /t 30 >nul
+shutdown.exe /r /t 00
+goto :end
+
+
+
+:recheck
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+ set /a total=%gpu_usage0%+%gpu_usage1%
+ set /a gpu_average=%total%/1
+goto :endrecheck
+:end
diff --git a/Utils/Monitor/Monitor_2card.bat b/Utils/Monitor/Monitor_2card.bat
new file mode 100644
index 0000000000..e3695133f7
--- /dev/null
+++ b/Utils/Monitor/Monitor_2card.bat
@@ -0,0 +1,86 @@
+@echo off
+mode con cols=50 lines=10
+cls
+:begin
+FOR /L %%A IN (60,-1,0) DO (
+ cls
+ echo Timeout [92;1m%%A[0m seconds...
+ timeout /t 1 >nul
+)
+:start
+cls
+:measure
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+set /a total=%gpu_usage0%+%gpu_usage1%
+set /a gpu_average=%total%/2
+
+:end_for
+cls
+echo Average Usage of *2 GPUs usage is %gpu_average%%%
+if %gpu_average% GTR 40 (
+ echo [92;1mMining is working[0m
+ echo [102;92;1mMining is working[0m
+ timeout /t 120 >nul
+ goto :start
+)
+
+set log_file=mining_problems_log.txt
+set ping_time=900
+FOR /F "skip=8 tokens=10" %%G in ('ping -n 3 google.com') DO set ping_time=%%G
+if %ping_time% GTR 0 (
+
+ echo Control checking of GPUs usage, timeout 120 sec...
+ timeout /t 120 >nul
+ goto:recheck
+ :endrecheck
+ if %gpu_average% GTR 40 (
+ echo ------------------- %date% %time% reboot warning>> %log_file%
+ goto :start
+ )
+ echo.
+ echo Average Usage of *2 GPUs usage is [93m%gpu_average%%%[0m
+ echo.
+
+ echo ping is [92m%ping_time%[0m - OK, not internet problem
+ timeout /t 120 >nul
+ goto :endif
+)
+:else
+ cls
+ echo %date% %time% No internet connection>> %log_file%
+ echo No internet connection, keep working...
+ timeout /t 120 >nul
+ goto :begin
+:endif
+
+SET mypath=%~dp0
+SET scrpath=%mypath%Scr
+if not exist "%scrpath%" mkdir "%scrpath%"
+
+rem "%mypath%nircmd.exe" savescreenshot "%scrpath%\%TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+echo "%scrpath%%DATE:~6,4%.%DATE:~3,2%.%DATE:~0,2% %TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+echo PC was restarted at %date% %time%>> %log_file%, mining issue. GPUs usage is %gpu_average%%%
+"nvidia-smi">> %log_file%
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+
+echo [101;93mMining is NOT working, rebooting in 10 seconds...[0m
+timeout /t 30 >nul
+shutdown.exe /r /t 00
+goto :end
+
+
+
+:recheck
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+ set /a total=%gpu_usage0%+%gpu_usage1%
+ set /a gpu_average=%total%/2
+goto :endrecheck
+:end
diff --git a/Utils/Monitor/Monitor_3card.bat b/Utils/Monitor/Monitor_3card.bat
new file mode 100644
index 0000000000..538956e2ef
--- /dev/null
+++ b/Utils/Monitor/Monitor_3card.bat
@@ -0,0 +1,90 @@
+@echo off
+mode con cols=50 lines=10
+cls
+:begin
+FOR /L %%A IN (60,-1,0) DO (
+ cls
+ echo Timeout [92;1m%%A[0m seconds...
+ timeout /t 1 >nul
+)
+:start
+cls
+:measure
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage2=%%p
+
+set /a total=%gpu_usage0%+%gpu_usage1%+%gpu_usage2%
+set /a gpu_average=%total%/3
+
+:end_for
+cls
+echo Average Usage of *3 GPUs usage is %gpu_average%%%
+if %gpu_average% GTR 40 (
+ echo [92;1mMining is working[0m
+ echo [102;92;1mMining is working[0m
+ timeout /t 120 >nul
+ goto :start
+)
+
+set log_file=mining_problems_log.txt
+set ping_time=900
+FOR /F "skip=8 tokens=10" %%G in ('ping -n 3 google.com') DO set ping_time=%%G
+if %ping_time% GTR 0 (
+
+ echo Control checking of GPUs usage, timeout 120 sec...
+ timeout /t 120 >nul
+ goto:recheck
+ :endrecheck
+ if %gpu_average% GTR 40 (
+ echo ------------------- %date% %time% reboot warning>> %log_file%
+ goto :start
+ )
+ echo.
+ echo Average Usage of *3 GPUs usage is [93m%gpu_average%%%[0m
+ echo.
+
+ echo ping is [92m%ping_time%[0m - OK, not internet problem
+ timeout /t 120 >nul
+ goto :endif
+)
+:else
+ cls
+ echo %date% %time% No internet connection>> %log_file%
+ echo No internet connection, keep working...
+ timeout /t 120 >nul
+ goto :begin
+:endif
+
+SET mypath=%~dp0
+SET scrpath=%mypath%Scr
+if not exist "%scrpath%" mkdir "%scrpath%"
+
+rem "%mypath%nircmd.exe" savescreenshot "%scrpath%\%TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+echo "%scrpath%%DATE:~6,4%.%DATE:~3,2%.%DATE:~0,2% %TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+echo PC was restarted at %date% %time%>> %log_file%, mining issue. GPUs usage is %gpu_average%%%
+"nvidia-smi">> %log_file%
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+
+echo [101;93mMining is NOT working, rebooting in 10 seconds...[0m
+timeout /t 30 >nul
+shutdown.exe /r /t 00
+goto :end
+
+
+
+:recheck
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage2=%%p
+
+ set /a total=%gpu_usage0%+%gpu_usage1%+%gpu_usage2%
+ set /a gpu_average=%total%/3
+goto :endrecheck
+:end
diff --git a/Utils/Monitor/Monitor_4card.bat b/Utils/Monitor/Monitor_4card.bat
new file mode 100644
index 0000000000..bdba640c1b
--- /dev/null
+++ b/Utils/Monitor/Monitor_4card.bat
@@ -0,0 +1,91 @@
+@echo off
+mode con cols=50 lines=10
+cls
+:begin
+FOR /L %%A IN (60,-1,0) DO (
+ cls
+ echo Timeout [92;1m%%A[0m seconds...
+ timeout /t 1 >nul
+)
+:start
+cls
+:measure
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage2=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage3=%%p
+
+set /a total=%gpu_usage0%+%gpu_usage1%+%gpu_usage2%+%gpu_usage3%
+set /a gpu_average=%total%/4
+
+:end_for
+cls
+echo Average Usage of *4 GPUs usage is %gpu_average%%%
+if %gpu_average% GTR 40 (
+ echo [92;1mMining is working[0m
+ echo [102;92;1mMining is working[0m
+ timeout /t 120 >nul
+ goto :start
+)
+
+set log_file=mining_problems_log.txt
+set ping_time=900
+FOR /F "skip=8 tokens=10" %%G in ('ping -n 3 google.com') DO set ping_time=%%G
+if %ping_time% GTR 0 (
+
+ echo Control checking of GPUs usage, timeout 120 sec...
+ timeout /t 120 >nul
+ goto:recheck
+ :endrecheck
+ if %gpu_average% GTR 40 (
+ echo ------------------- %date% %time% reboot warning>> %log_file%
+ goto :start
+ )
+ echo.
+ echo Average Usage of *4 GPUs usage is [93m%gpu_average%%%[0m
+ echo.
+
+ echo ping is [92m%ping_time%[0m - OK, not internet problem
+ timeout /t 120 >nul
+ goto :endif
+)
+:else
+ cls
+ echo %date% %time% No internet connection>> %log_file%
+ echo No internet connection, keep working...
+ timeout /t 120 >nul
+ goto :begin
+:endif
+
+SET mypath=%~dp0
+SET scrpath=%mypath%Scr
+if not exist "%scrpath%" mkdir "%scrpath%"
+
+rem "%mypath%nircmd.exe" savescreenshot "%scrpath%\%TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+echo "%scrpath%%DATE:~6,4%.%DATE:~3,2%.%DATE:~0,2% %TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+echo PC was restarted at %date% %time%>> %log_file%, mining issue. GPUs usage is %gpu_average%%%
+"nvidia-smi">> %log_file%
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+
+echo [101;93mMining is NOT working, rebooting in 10 seconds...[0m
+timeout /t 30 >nul
+shutdown.exe /r /t 00
+goto :end
+
+
+
+:recheck
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage2=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage3=%%p
+ set /a total=%gpu_usage0%+%gpu_usage1%+%gpu_usage2%+%gpu_usage3%
+ set /a gpu_average=%total%/4
+goto :endrecheck
+:end
diff --git a/Utils/Monitor/Monitor_5card.bat b/Utils/Monitor/Monitor_5card.bat
new file mode 100644
index 0000000000..f64c18bd8d
--- /dev/null
+++ b/Utils/Monitor/Monitor_5card.bat
@@ -0,0 +1,92 @@
+@echo off
+mode con cols=50 lines=10
+cls
+:begin
+FOR /L %%A IN (60,-1,0) DO (
+ cls
+ echo Timeout [92;1m%%A[0m seconds...
+ timeout /t 1 >nul
+)
+:start
+cls
+:measure
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage2=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage3=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage4=%%p
+set /a total=%gpu_usage0%+%gpu_usage1%+%gpu_usage2%+%gpu_usage3%+%gpu_usage4%
+set /a gpu_average=%total%/5
+
+:end_for
+cls
+echo Average Usage of *5 GPUs usage is %gpu_average%%%
+if %gpu_average% GTR 5 (
+ echo [92;1mMining is working[0m
+ echo [102;92;1mMining is working[0m
+ timeout /t 120 >nul
+ goto :start
+)
+
+set log_file=mining_problems_log.txt
+set ping_time=900
+FOR /F "skip=8 tokens=10" %%G in ('ping -n 3 google.com') DO set ping_time=%%G
+if %ping_time% GTR 0 (
+
+ echo Control checking of GPUs usage, timeout 120 sec...
+ timeout /t 120 >nul
+ goto:recheck
+ :endrecheck
+ if %gpu_average% GTR 40 (
+ echo ------------------- %date% %time% reboot warning>> %log_file%
+ goto :start
+ )
+ echo.
+ echo Average Usage of *5 GPUs usage is [93m%gpu_average%%%[0m
+ echo.
+
+ echo ping is [92m%ping_time%[0m - OK, not internet problem
+ timeout /t 120 >nul
+ goto :endif
+)
+:else
+ cls
+ echo %date% %time% No internet connection>> %log_file%
+ echo No internet connection, keep working...
+ timeout /t 120 >nul
+ goto :begin
+:endif
+
+SET mypath=%~dp0
+SET scrpath=%mypath%Scr
+if not exist "%scrpath%" mkdir "%scrpath%"
+
+rem "%mypath%nircmd.exe" savescreenshot "%scrpath%\%TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+echo "%scrpath%%DATE:~6,4%.%DATE:~3,2%.%DATE:~0,2% %TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+echo PC was restarted at %date% %time%>> %log_file%, mining issue. GPUs usage is %gpu_average%%%
+"nvidia-smi">> %log_file%
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+
+echo [101;93mMining is NOT working, rebooting in 10 seconds...[0m
+timeout /t 30 >nul
+shutdown.exe /r /t 00
+goto :end
+
+
+
+:recheck
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage2=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage3=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage4=%%p
+ set /a total=%gpu_usage0%+%gpu_usage1%+%gpu_usage2%+%gpu_usage3%+%gpu_usage4%
+ set /a gpu_average=%total%/5
+goto :endrecheck
+:end
diff --git a/Utils/Monitor/Monitor_6card.bat b/Utils/Monitor/Monitor_6card.bat
new file mode 100644
index 0000000000..720ab96cc9
--- /dev/null
+++ b/Utils/Monitor/Monitor_6card.bat
@@ -0,0 +1,94 @@
+@echo off
+mode con cols=50 lines=10
+cls
+:begin
+FOR /L %%A IN (120,-1,0) DO (
+ cls
+ echo Timeout [92;1m%%A[0m seconds...
+ timeout /t 1 >nul
+)
+:start
+cls
+:measure
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage2=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage3=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage4=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage5=%%p
+set /a total=%gpu_usage0%+%gpu_usage1%+%gpu_usage2%+%gpu_usage3%+%gpu_usage4%+%gpu_usage5%
+set /a gpu_average=%total%/6
+
+:end_for
+cls
+echo Average Usage of *6 GPUs usage is %gpu_average%%%
+if %gpu_average% GTR 5 (
+ echo [92;1mMining is working[0m
+ echo [102;92;1mMining is working[0m
+ timeout /t 120 >nul
+ goto :start
+)
+
+set log_file=mining_problems_log.txt
+set ping_time=900
+FOR /F "skip=8 tokens=10" %%G in ('ping -n 3 google.com') DO set ping_time=%%G
+if %ping_time% GTR 0 (
+
+ echo Control checking of GPUs usage, timeout 120 sec...
+ timeout /t 120 >nul
+ goto:recheck
+ :endrecheck
+ if %gpu_average% GTR 40 (
+ echo ------------------- %date% %time% reboot warning>> %log_file%
+ goto :start
+ )
+ echo.
+ echo Average Usage of *6 GPUs usage is [93m%gpu_average%%%[0m
+ echo.
+
+ echo ping is [92m%ping_time%[0m - OK, not internet problem
+ timeout /t 120 >nul
+ goto :endif
+)
+:else
+ cls
+ echo %date% %time% No internet connection>> %log_file%
+ echo No internet connection, keep working...
+ timeout /t 120 >nul
+ goto :begin
+:endif
+
+SET mypath=%~dp0
+SET scrpath=%mypath%Scr
+if not exist "%scrpath%" mkdir "%scrpath%"
+
+rem "%mypath%nircmd.exe" savescreenshot "%scrpath%\%TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+echo "%scrpath%%DATE:~6,4%.%DATE:~3,2%.%DATE:~0,2% %TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+echo PC was restarted at %date% %time%>> %log_file%, mining issue. GPUs usage is %gpu_average%%%
+"nvidia-smi">> %log_file%
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+
+echo [101;93mMining is NOT working, rebooting in 10 seconds...[0m
+timeout /t 30 >nul
+shutdown.exe /r /t 00
+goto :end
+
+
+
+:recheck
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage2=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage3=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage4=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage5=%%p
+ set /a total=%gpu_usage0%+%gpu_usage1%+%gpu_usage2%+%gpu_usage3%+%gpu_usage4%+%gpu_usage5%
+ set /a gpu_average=%total%/6
+goto :endrecheck
+:end
diff --git a/Utils/Monitor/Monitor_7card.bat b/Utils/Monitor/Monitor_7card.bat
new file mode 100644
index 0000000000..9aea971f42
--- /dev/null
+++ b/Utils/Monitor/Monitor_7card.bat
@@ -0,0 +1,96 @@
+@echo off
+mode con cols=50 lines=10
+cls
+:begin
+FOR /L %%A IN (60,-1,0) DO (
+ cls
+ echo Timeout [92;1m%%A[0m seconds...
+ timeout /t 1 >nul
+)
+:start
+cls
+:measure
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage2=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage3=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage4=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage5=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage6=%%p
+set /a total=%gpu_usage0%+%gpu_usage1%+%gpu_usage2%+%gpu_usage3%+%gpu_usage4%+%gpu_usage5%+%gpu_usage6%
+set /a gpu_average=%total%/7
+
+:end_for
+cls
+echo Average Usage of *7 GPUs usage is %gpu_average%%%
+if %gpu_average% GTR 40 (
+ echo [92;1mMining is working[0m
+ echo [102;92;1mMining is working[0m
+ timeout /t 120 >nul
+ goto :start
+)
+
+set log_file=mining_problems_log.txt
+set ping_time=900
+FOR /F "skip=8 tokens=10" %%G in ('ping -n 3 google.com') DO set ping_time=%%G
+if %ping_time% GTR 0 (
+
+ echo Control checking of GPUs usage, timeout 120 sec...
+ timeout /t 120 >nul
+ goto:recheck
+ :endrecheck
+ if %gpu_average% GTR 40 (
+ echo ------------------- %date% %time% reboot warning>> %log_file%
+ goto :start
+ )
+ echo.
+ echo Average Usage of *7 GPUs usage is [93m%gpu_average%%%[0m
+ echo.
+
+ echo ping is [92m%ping_time%[0m - OK, not internet problem
+ timeout /t 120 >nul
+ goto :endif
+)
+:else
+ cls
+ echo %date% %time% No internet connection>> %log_file%
+ echo No internet connection, keep working...
+ timeout /t 120 >nul
+ goto :begin
+:endif
+
+SET mypath=%~dp0
+SET scrpath=%mypath%Scr
+if not exist "%scrpath%" mkdir "%scrpath%"
+
+rem "%mypath%nircmd.exe" savescreenshot "%scrpath%\%TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+echo "%scrpath%%DATE:~6,4%.%DATE:~3,2%.%DATE:~0,2% %TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+echo PC was restarted at %date% %time%>> %log_file%, mining issue. GPUs usage is %gpu_average%%%
+"nvidia-smi">> %log_file%
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+
+echo [101;93mMining is NOT working, rebooting in 10 seconds...[0m
+timeout /t 30 >nul
+shutdown.exe /r /t 00
+goto :end
+
+
+
+:recheck
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage2=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage3=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage4=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage5=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage6=%%p
+ set /a total=%gpu_usage0%+%gpu_usage1%+%gpu_usage2%+%gpu_usage3%+%gpu_usage4%+%gpu_usage5%+%gpu_usage6%
+ set /a gpu_average=%total%/7
+goto :endrecheck
+:end
diff --git a/Utils/Monitor/Monitor_8card.bat b/Utils/Monitor/Monitor_8card.bat
new file mode 100644
index 0000000000..ca53559bb8
--- /dev/null
+++ b/Utils/Monitor/Monitor_8card.bat
@@ -0,0 +1,98 @@
+@echo off
+mode con cols=50 lines=10
+cls
+:begin
+FOR /L %%A IN (60,-1,0) DO (
+ cls
+ echo Timeout [92;1m%%A[0m seconds...
+ timeout /t 1 >nul
+)
+:start
+cls
+:measure
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage2=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage3=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage4=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage5=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage6=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage7=%%p
+set /a total=%gpu_usage0%+%gpu_usage1%+%gpu_usage2%+%gpu_usage3%+%gpu_usage4%+%gpu_usage5%+%gpu_usage6%+%gpu_usage7%
+set /a gpu_average=%total%/8
+
+:end_for
+cls
+echo Average Usage of *8 GPUs usage is %gpu_average%%%
+if %gpu_average% GTR 40 (
+ echo [92;1mMining is working[0m
+ echo [102;92;1mMining is working[0m
+ timeout /t 120 >nul
+ goto :start
+)
+
+set log_file=mining_problems_log.txt
+set ping_time=900
+FOR /F "skip=8 tokens=10" %%G in ('ping -n 3 google.com') DO set ping_time=%%G
+if %ping_time% GTR 0 (
+
+ echo Control checking of GPUs usage, timeout 120 sec...
+ timeout /t 120 >nul
+ goto:recheck
+ :endrecheck
+ if %gpu_average% GTR 40 (
+ echo ------------------- %date% %time% reboot warning>> %log_file%
+ goto :start
+ )
+ echo.
+ echo Average Usage of *2 GPUs usage is [93m%gpu_average%%%[0m
+ echo.
+
+ echo ping is [92m%ping_time%[0m - OK, not internet problem
+ timeout /t 120 >nul
+ goto :endif
+)
+:else
+ cls
+ echo %date% %time% No internet connection>> %log_file%
+ echo No internet connection, keep working...
+ timeout /t 120 >nul
+ goto :begin
+:endif
+
+SET mypath=%~dp0
+SET scrpath=%mypath%Scr
+if not exist "%scrpath%" mkdir "%scrpath%"
+
+rem "%mypath%nircmd.exe" savescreenshot "%scrpath%\%TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+echo "%scrpath%%DATE:~6,4%.%DATE:~3,2%.%DATE:~0,2% %TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+echo PC was restarted at %date% %time%>> %log_file%, mining issue. GPUs usage is %gpu_average%%%
+"nvidia-smi">> %log_file%
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+
+echo [101;93mMining is NOT working, rebooting in 10 seconds...[0m
+timeout /t 30 >nul
+shutdown.exe /r /t 00
+goto :end
+
+
+
+:recheck
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage2=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage3=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage4=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage5=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage6=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage7=%%p
+ set /a total=%gpu_usage0%+%gpu_usage1%+%gpu_usage2%+%gpu_usage3%+%gpu_usage4%+%gpu_usage5%+%gpu_usage6%+%gpu_usage7%
+ set /a gpu_average=%total%/8
+goto :endrecheck
+:end
diff --git a/Utils/Monitor/Monitor_9card.bat b/Utils/Monitor/Monitor_9card.bat
new file mode 100644
index 0000000000..c8f2ed2105
--- /dev/null
+++ b/Utils/Monitor/Monitor_9card.bat
@@ -0,0 +1,100 @@
+@echo off
+mode con cols=50 lines=10
+cls
+:begin
+FOR /L %%A IN (120,-1,0) DO (
+ cls
+ echo Timeout [92;1m%%A[0m seconds...
+ timeout /t 1 >nul
+)
+:start
+cls
+:measure
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage2=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage3=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage4=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage5=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage6=%%p
+for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage7=%%p
+for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage8=%%p
+set /a total=%gpu_usage0%+%gpu_usage1%+%gpu_usage2%+%gpu_usage3%+%gpu_usage4%+%gpu_usage5%+%gpu_usage6%+%gpu_usage7%+%gpu_usage8%
+set /a gpu_average=%total%/9
+
+:end_for
+cls
+echo Average Usage of *9 GPUs usage is %gpu_average%%%
+if %gpu_average% GTR 40 (
+ echo [92;1mMining is working[0m
+ echo [102;92;1mMining is working[0m
+ timeout /t 120 >nul
+ goto :start
+)
+
+set log_file=mining_problems_log.txt
+set ping_time=900
+FOR /F "skip=8 tokens=10" %%G in ('ping -n 3 google.com') DO set ping_time=%%G
+if %ping_time% GTR 0 (
+
+ echo Control checking of GPUs usage, timeout 120 sec...
+ timeout /t 120 >nul
+ goto:recheck
+ :endrecheck
+ if %gpu_average% GTR 40 (
+ echo ------------------- %date% %time% reboot warning>> %log_file%
+ goto :start
+ )
+ echo.
+ echo Average Usage of *9 GPUs usage is [93m%gpu_average%%%[0m
+ echo.
+
+ echo ping is [92m%ping_time%[0m - OK, not internet problem
+ timeout /t 120 >nul
+ goto :endif
+)
+:else
+ cls
+ echo %date% %time% No internet connection>> %log_file%
+ echo No internet connection, keep working...
+ timeout /t 120 >nul
+ goto :begin
+:endif
+
+SET mypath=%~dp0
+SET scrpath=%mypath%Scr
+if not exist "%scrpath%" mkdir "%scrpath%"
+
+rem "%mypath%nircmd.exe" savescreenshot "%scrpath%\%TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+echo "%scrpath%%DATE:~6,4%.%DATE:~3,2%.%DATE:~0,2% %TIME:~0,-9%-%TIME:~3,2%-%TIME:~6,2%.png"
+
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+echo PC was restarted at %date% %time%>> %log_file%, mining issue. GPUs usage is %gpu_average%%%
+"nvidia-smi">> %log_file%
+echo.>> %log_file%
+echo ---------------------------------------------------------------------------------------------------->> %log_file%
+echo.>> %log_file%
+
+echo [101;93mMining is NOT working, rebooting in 10 seconds...[0m
+timeout /t 30 >nul
+shutdown.exe /r /t 00
+goto :end
+
+
+
+:recheck
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage0=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage1=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage2=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage3=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage4=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage5=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage6=%%p
+ for /F %%p in ('"nvidia-smi" --id^=1 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage7=%%p
+ for /F %%p in ('"nvidia-smi" --id^=0 --query-gpu^=utilization.gpu --format^=csv^,noheader^,nounits') do set gpu_usage8=%%p
+ set /a total=%gpu_usage0%+%gpu_usage1%+%gpu_usage2%+%gpu_usage3%+%gpu_usage4%+%gpu_usage5%+%gpu_usage6%+%gpu_usage7%+%gpu_usage7%
+ set /a gpu_average=%total%/9
+goto :endrecheck
+:end
diff --git a/Utils/Monitor/Readme.txt b/Utils/Monitor/Readme.txt
new file mode 100644
index 0000000000..91ad163289
--- /dev/null
+++ b/Utils/Monitor/Readme.txt
@@ -0,0 +1,3 @@
+Replace the GTR 40 with GTR 70. This way, if a single card fails, it would still detect as a failure and reboot.
+A single card dying is 66.66% GPU usage, so would still be considered "Mining is working" if it was set to detect at 40.
+This is an option for you to go in and edit one of these bat files that is equivalent with the number of cards you have on your system.
diff --git a/Utils/Monitor/nvidia-smi.1.pdf b/Utils/Monitor/nvidia-smi.1.pdf
new file mode 100644
index 0000000000..c101ff41e3
Binary files /dev/null and b/Utils/Monitor/nvidia-smi.1.pdf differ
diff --git a/Utils/Monitor/nvidia-smi.exe b/Utils/Monitor/nvidia-smi.exe
new file mode 100644
index 0000000000..d005a42704
Binary files /dev/null and b/Utils/Monitor/nvidia-smi.exe differ
diff --git a/Utils/Monitor/nvml.dll b/Utils/Monitor/nvml.dll
new file mode 100644
index 0000000000..a0120bf3f5
Binary files /dev/null and b/Utils/Monitor/nvml.dll differ
diff --git a/Utils/NemosMiner_LogReader.xml b/Utils/NemosMiner_LogReader.xml
new file mode 100644
index 0000000000..185dcc1245
--- /dev/null
+++ b/Utils/NemosMiner_LogReader.xml
@@ -0,0 +1,199 @@
+
+
+
+
+ ..\Logs\NemosMiner_????-??-??.log
+ System.Text.UTF8Encoding
+ 1000
+ 10
+ 500
+ true
+ true
+ White
+ Black
+ Consolas, 9pt
+ Yellow
+ DarkGreen
+ false
+ NemosMiner_2021-08-31.log
+ Maximized
+
+ 1395
+ 596
+
+
+ -11
+ -45
+
+
+
+
+ true
+ false
+
+
+ Benchmark.+for .+ in progress|Power usage measurement for.+ in progress
+ false
+ true
+ false
+ true
+ false
+ #FF8000
+ Black
+
+
+ Benchmark done|Power usage measurement done
+ false
+ true
+ false
+ true
+ false
+ #FFC082
+ Black
+
+
+ Reported worker status to monitoring server|Retrieved worker status from
+ false
+ true
+ false
+ true
+ true
+ #55AAAA
+ Black
+
+
+ Some miners binaries are missing, starting downloader...
+ false
+ false
+ false
+ true
+ false
+ Fuchsia
+ Black
+
+
+ Downloader:
+ false
+ false
+ false
+ true
+ false
+ #FF80FF
+ Black
+
+
+ more profitable than the fastest miner:
+ false
+ false
+ false
+ true
+ false
+ #400040
+ #FFFF80
+
+
+ Starting NemosMiner|Using configuration file|Web GUI and API.+ running
+ false
+ true
+ false
+ true
+ false
+ Aqua
+ Black
+
+
+ Started idle detection|Mining is suspended until system is idle again|Stopped idle detection
+ false
+ true
+ false
+ true
+ false
+ Gray
+ Black
+
+
+ Donation run
+ false
+ false
+ false
+ true
+ false
+ Silver
+ #400040
+
+
+ ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} \w+: Started new cycle|^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} \w+: Collecting miner data while|^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} \w+:.Ending cycle
+ false
+ true
+ false
+ true
+ false
+ #0080FF
+ Black
+
+
+ ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} \w+: Stopping miner .*
+ false
+ true
+ false
+ true
+ false
+ #00AC00
+ Black
+
+
+ ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} \w+: Starting miner .*
+ false
+ true
+ false
+ true
+ false
+ #00E600
+ Black
+
+
+ ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} WARN:.*
+ false
+ true
+ false
+ true
+ false
+ #FFFF80
+ Black
+
+
+ ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} ERROR:.*
+ false
+ true
+ false
+ true
+ true
+ White
+ Red
+
+
+ Stopped idle detection
+ false
+ false
+ false
+ true
+ true
+ White
+ Black
+
+
+
+
+
+ 0
+
+ 1399
+ 700
+
+
+ 19
+ 20
+
+ false
+ false
+
\ No newline at end of file
diff --git a/Utils/NoDevFee.exe b/Utils/NoDevFee.exe
new file mode 100644
index 0000000000..ee3d19a21f
Binary files /dev/null and b/Utils/NoDevFee.exe differ
diff --git a/Utils/NvidiaDriverRepacker/LICENSE b/Utils/NvidiaDriverRepacker/LICENSE
new file mode 100644
index 0000000000..a714cf2686
--- /dev/null
+++ b/Utils/NvidiaDriverRepacker/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2018, XhmikosR.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/Utils/NvidiaDriverRepacker/README.md b/Utils/NvidiaDriverRepacker/README.md
new file mode 100644
index 0000000000..414aa46a50
--- /dev/null
+++ b/Utils/NvidiaDriverRepacker/README.md
@@ -0,0 +1,42 @@
+# slim-nvidia-drivers
+
+This is a Windows script which simply removes the unneeded stuff/bloatware from NVIDIA drivers
+package and creates a new archive.
+
+**WARNING**: USE AT YOUR OWN RISK!
+
+**Make sure you get the file from the [Releases section](https://github.com/XhmikosR/slim-nvidia-drivers/releases), otherwise you will have issues with unix line endings!**
+
+## Drivers tested:
+
+* \>= v440.97: use v0.5
+* \>= v411.63: use v0.3
+* \>= v397.93: use v0.2
+* v388 - v391: use v0.1
+
+### Cards tested
+
+Note that the resulting drivers have been tested on GTX 1060, GTX 1070 and MX 150 cards. If you own a newer card that needs other components to be included, please make a Pull Request.
+
+## Requirements:
+
+* a) [7-Zip](https://www.7-zip.org/download.html) installed or b) [7za.exe](https://www.7-zip.org/download.html) in your `%PATH%`, or in the same folder as this script
+* A recent Windows version; the script is only tested on Windows 10
+* The NVIDIA driver already downloaded somewhere on your computer :)
+
+## Usage:
+
+```
+slim-nvidia-drivers.bat NVIDIA_DRIVER_FILE.exe
+```
+
+Or just drag and drop the `NVIDIA_DRIVER_FILE.exe` on the bat file.
+
+This will create two 7z archives, minimal and slim:
+
+* "minimal" includes only the driver
+* "slim" includes the driver, HDAudio and PhysX
+
+## License
+
+[MIT](LICENSE)
diff --git a/Utils/NvidiaDriverRepacker/howto.txt b/Utils/NvidiaDriverRepacker/howto.txt
new file mode 100644
index 0000000000..bf7ec9f5a9
--- /dev/null
+++ b/Utils/NvidiaDriverRepacker/howto.txt
@@ -0,0 +1,18 @@
+This is a Windows script which simply removes the unneeded stuff/bloatware from NVIDIA drivers package and creates a new archive.
+
+Requirements:
+a) 7-Zip installed or b) 7za.exe in your %PATH%, or in the same folder as this script
+A recent Windows version; the script is only tested on Windows 10
+
+how to remove all un-needed bloatware/telemetry from Latest Nvidia Drivers
+
+simply download your Driver From: https://www.nvidia.com/Download/index.aspx
+
+once downloaded, place downloaded driver in this folder, drag and drop the NVIDIA_DRIVER_FILE.exe on the bat file "slim-nvidia-drivers.bat"
+
+this will automatically create two 7z files from the orignal Driver File
+
+"minimal" includes only the driver
+"slim" includes the driver, HDAudio and PhysX
+
+Happy Mining
diff --git a/Utils/NvidiaDriverRepacker/slim-nvidia-drivers.bat b/Utils/NvidiaDriverRepacker/slim-nvidia-drivers.bat
new file mode 100644
index 0000000000..b8ad2a8dab
--- /dev/null
+++ b/Utils/NvidiaDriverRepacker/slim-nvidia-drivers.bat
@@ -0,0 +1,228 @@
+@echo off
+
+rem --------------------------------------------------
+rem A Windows batch file to slim down NVIDIA drivers.
+rem Author: XhmikosR
+rem Licensed under the MIT License
+rem See help for more info
+rem --------------------------------------------------
+
+
+:start
+setlocal
+
+set "FOLDERS_TO_KEEP_MINIMAL=Display.Driver NVI2"
+set "FOLDERS_TO_KEEP_SLIM=Display.Driver HDAudio NVI2 PhysX PPC"
+set "FILES_TO_KEEP_MINIMAL=EULA.txt ListDevices.txt setup.cfg setup.exe"
+set "FILES_TO_KEEP_SLIM=%FILES_TO_KEEP_MINIMAL%"
+
+set "BATCH_FILENAME=%~nx0"
+set "ARG1=%~1"
+set "FULL_PATH=%ARG1%"
+set "FILENAME=%~n1"
+set "WORK_FOLDER=%FILENAME%"
+set "SCRIPT_VERSION=0.5"
+
+title %BATCH_FILENAME% %FILENAME%
+
+rem Check if any argument is passed; if not show the help screen
+if "%ARG1%" == "" goto help
+if "%ARG1%" == "--help" goto help
+if "%ARG1%" == "-help" goto help
+if "%ARG1%" == "/help" goto help
+
+rem Try to detect 7-Zip or 7za.exe; if none is found, show a message and exit
+call :detect_sevenzip_path
+
+if not exist "%SEVENZIP%" (
+ echo 7-Zip or 7za.exe wasn't found!
+ echo You can install 7-Zip, or place 7za.exe in your %%PATH%%, or in the same folder as this script.
+ goto exit
+)
+
+rem Switch to the batch file's directory
+cd /d %~dp0
+
+rem If the file doesn't exist show a message and exit
+if not exist "%FULL_PATH%" (
+ echo "%FULL_PATH%" wasn't found! & goto exit
+)
+
+rem Remove the old folder if it exists
+if exist "%WORK_FOLDER%" rd /q /s "%WORK_FOLDER%"
+
+rem Extract the driver
+"%SEVENZIP%" x "%FULL_PATH%" -o"%WORK_FOLDER%"
+if %ERRORLEVEL% neq 0 (
+ echo. & echo *** [ERROR] Extracting "%FULL_PATH%" failed! & echo.
+ goto exit
+)
+
+rem Switch to the drivers folder
+pushd "%WORK_FOLDER%"
+
+rem Minimal
+call :copy "minimal"
+if ERRORLEVEL 1 goto exit
+call :modify_setup_cfg
+if ERRORLEVEL 1 goto exit
+call :create_archive "minimal"
+if ERRORLEVEL 1 goto exit
+
+rem Slim
+call :copy "slim"
+if ERRORLEVEL 1 goto exit
+call :modify_setup_cfg
+if ERRORLEVEL 1 goto exit
+call :create_archive "slim"
+if ERRORLEVEL 1 goto exit
+
+popd
+
+rem Remove the drivers folder
+rd /q /s "%WORK_FOLDER%"
+
+
+:exit
+endlocal
+echo. & echo Press any key to close this window...
+pause >nul
+exit /b
+
+
+rem Subroutines
+:help
+echo --------------------------------------------------
+echo %BATCH_FILENAME% v%SCRIPT_VERSION%
+echo A Windows batch file to slim down NVIDIA drivers.
+echo Author: XhmikosR
+echo Licensed under the MIT License
+echo.
+echo Requirements:
+echo * a) 7-Zip installed or b) 7za.exe in your %%PATH%%, or in the same folder as this script
+echo * A recent Windows version; the script is only tested on Windows 10
+echo * The NVIDIA driver already downloaded somewhere on your computer :)
+echo.
+echo Usage: %BATCH_FILENAME% NVIDIA_DRIVER_FILE.exe
+echo.
+echo This will create two 7z archives, minimal and slim:
+echo * "minimal" includes only the driver
+echo * "slim" includes the driver, HDAudio, PhysX and USB-C HDMI Driver
+echo --------------------------------------------------
+goto exit
+
+
+:copy
+set "TYPE=%~1"
+set "TEMP_DIR=_temp_%TYPE%"
+
+rem Create a temporary folder
+if not exist "%TEMP_DIR%" mkdir "%TEMP_DIR%"
+
+rem Copy all the things
+call :copy_folders "%TYPE%"
+if ERRORLEVEL 1 exit /b %ERRORLEVEL%
+call :copy_files "%TYPE%"
+if ERRORLEVEL 1 exit /b %ERRORLEVEL%
+
+exit /b 0
+
+
+:copy_folders
+if "%TYPE%" == "minimal" (
+ set "TEMP_FOLDERS_TO_KEEP=%FOLDERS_TO_KEEP_MINIMAL%"
+) else (
+ set "TEMP_FOLDERS_TO_KEEP=%FOLDERS_TO_KEEP_SLIM%"
+)
+
+rem Copy the folders we want to keep into the temporary folder
+for /d %%G in (%TEMP_FOLDERS_TO_KEEP%) do (
+ if not exist "%%G" (
+ echo. & echo *** [ERROR] "%%G" doesn't exist in the drivers file! & echo.
+ exit /b 1
+ )
+
+ xcopy "%%G" "%TEMP_DIR%\%%G" /i /s /h /e /k /q /r /y /v
+ if %ERRORLEVEL% neq 0 (
+ echo. & echo *** [ERROR] Copying folders failed! & echo.
+ exit /b 1
+ )
+)
+
+exit /b 0
+
+
+:copy_files
+if "%TYPE%" == "minimal" (
+ set "TEMP_FILES_TO_KEEP=%FILES_TO_KEEP_MINIMAL%"
+) else (
+ set "TEMP_FILES_TO_KEEP=%FILES_TO_KEEP_SLIM%"
+)
+
+rem Copy the files we want to keep into the temporary folder
+for %%G in (%TEMP_FILES_TO_KEEP%) do (
+ if not exist "%%G" (
+ echo. & echo *** [ERROR] "%%G" doesn't exist in the drivers file! & echo.
+ exit /b 1
+ )
+
+ copy /y /v "%%G" "%TEMP_DIR%\"
+ if %ERRORLEVEL% neq 0 (
+ echo. & echo *** [ERROR] Copying files failed! & echo.
+ exit /b 1
+ )
+)
+
+exit /b 0
+
+
+:modify_setup_cfg
+rem Remove the files required after 397.93, but are not needed
+type "%TEMP_DIR%\setup.cfg" | findstr /v "EulaHtmlFile FunctionalConsentFile PrivacyPolicyFile">"%TEMP_DIR%\setup2.cfg"
+if ERRORLEVEL 1 exit /b %ERRORLEVEL%
+
+rem Overwrite the origin setup.cfg file
+move /y "%TEMP_DIR%\setup2.cfg" "%TEMP_DIR%\setup.cfg"
+if ERRORLEVEL 1 exit /b %ERRORLEVEL%
+
+exit /b 0
+
+
+:create_archive
+rem Rename the temporary directory
+set "TEMP_ARCHIVE_DIR=%FILENAME%_%TYPE%"
+rename "%TEMP_DIR%" "%TEMP_ARCHIVE_DIR%"
+
+rem Just in case NUMBER_OF_PROCESSORS isn't defined
+if not defined NUMBER_OF_PROCESSORS set NUMBER_OF_PROCESSORS=4
+
+rem Create the new archive
+start "7-Zip" /b /wait "%SEVENZIP%" a -t7z ""%TEMP_ARCHIVE_DIR%.7z"" ""%TEMP_ARCHIVE_DIR%\*"" -mmt=%NUMBER_OF_PROCESSORS% -m0=LZMA2 -mx9
+
+if %ERRORLEVEL% neq 0 (
+ echo. & echo *** [ERROR] Creating 7z archive! & echo.
+ exit /b 1
+)
+
+move /y "%TEMP_ARCHIVE_DIR%.7z" ".."
+
+rem Remove the temporary folders
+if exist "%TEMP_DIR%" rd /q /s "%TEMP_DIR%"
+if exist "%TEMP_ARCHIVE_DIR%" rd /q /s "%TEMP_ARCHIVE_DIR%"
+
+exit /b 0
+
+
+:detect_sevenzip_path
+if exist 7za.exe (set "SEVENZIP=7za.exe" & exit /b)
+
+for %%G in (7z.exe) do (set "SEVENZIP_PATH=%%~$PATH:G")
+if exist "%SEVENZIP_PATH%" (set "SEVENZIP=%SEVENZIP_PATH%" & exit /b)
+
+for %%G in (7za.exe) do (set "SEVENZIP_PATH=%%~$PATH:G")
+if exist "%SEVENZIP_PATH%" (set "SEVENZIP=%SEVENZIP_PATH%" & exit /b)
+
+for /f "tokens=2*" %%A in (
+ 'reg QUERY "HKLM\SOFTWARE\7-Zip" /v "Path" 2^>nul ^| find "REG_SZ" ^|^|
+ reg QUERY "HKLM\SOFTWARE\Wow6432Node\7-Zip" /v "Path" 2^>nul ^| find "REG_SZ"') do set "SEVENZIP=%%B\7z.exe"
+exit /b 0
diff --git a/Utils/RemoveLogs.bat b/Utils/RemoveLogs.bat
new file mode 100644
index 0000000000..87c21831d2
--- /dev/null
+++ b/Utils/RemoveLogs.bat
@@ -0,0 +1,12 @@
+@echo off
+cd /d %~dp0
+set /p execute=This process will delete all unnecessary log files created by the miners and NemosMiner to free up space. Are you sure you want to continue? [Y/N]
+IF /I "%execute%"=="Y" (
+ cd .\Bin
+ for /f "delims=" %%F in ('dir /b /s "*.log"') do @del "%%F"
+ cd ..\Logs
+ for /f "delims=" %%F in ('dir /b /s "*.log"') do @del "%%F"
+ cd ..
+ ECHO All existing log files have been successfully deleted.
+ PAUSE
+)
diff --git a/Utils/ResetBenchmark.bat b/Utils/ResetBenchmark.bat
new file mode 100644
index 0000000000..c10a4a56a6
--- /dev/null
+++ b/Utils/ResetBenchmark.bat
@@ -0,0 +1,8 @@
+@echo off
+cd /d %~dp0
+set /p benchreset=This process will remove all benchmarking data. Are you sure you want to continue? [Y/N]
+IF /I "%benchreset%"=="Y" (
+ if exist "Stats\*_HashRate.txt" del "Stats\*_HashRate.txt"
+ ECHO Success. You need to re-benchmark all miners to continue using MultiPoolMiner.
+ PAUSE
+)
diff --git a/Utils/ResetPowerUsage.bat b/Utils/ResetPowerUsage.bat
new file mode 100644
index 0000000000..21876bfb9f
--- /dev/null
+++ b/Utils/ResetPowerUsage.bat
@@ -0,0 +1,9 @@
+@echo off
+cd /d %~dp0
+set /p powerusagereset=This process will remove all power usage data. Are you sure you want to continue? [Y/N]
+IF /I "%powerusagereset%"=="Y" (
+ if exist "Stats\*_PowerUsage.txt" del "Stats\*_PowerUsage.txt"
+ if exist "Stats\PowerUsage\*_PowerUsage.txt" del "Stats\PowerUsage\*_PowerUsage.txt"
+ ECHO Success. You need to measure the power consumption for all required miners ^& algorithms to continue using MultiPoolMiner.
+ PAUSE
+)
diff --git a/Utils/ResetProfit.bat b/Utils/ResetProfit.bat
new file mode 100644
index 0000000000..53d7a78e1e
--- /dev/null
+++ b/Utils/ResetProfit.bat
@@ -0,0 +1,9 @@
+@echo off
+cd /d %~dp0
+set /p statreset=This process will remove all accumulated coin data and reset your profit statistics. Are you sure you want to continue? [Y/N]
+IF /I "%statreset%"=="Y" (
+ if exist "Stats\*Profit.txt" del "Stats\*Profit.txt"
+ if exist "Stats\Profit\*Profit.txt" del "Stats\Profit\*Profit.txt"
+ ECHO Your stats have been successfully reset.
+ PAUSE
+)
diff --git a/Utils/Restart HWInfo64.cmd b/Utils/Restart HWInfo64.cmd
new file mode 100644
index 0000000000..3aa4aaf273
--- /dev/null
+++ b/Utils/Restart HWInfo64.cmd
@@ -0,0 +1,7 @@
+rem @echo off
+taskkill /IM HWiNFO64.EXE /T > nul
+ping localhost -n 5 > nul
+taskkill /IM HWiNFO64.EXE /T > nul
+start "" "C:\Program Files\Tools\HWiNFO64.EXE"
+rem "C:\Program Files\Tools\MSI Afterburner\MSIAfterburner.exe" -profile1
+exit
\ No newline at end of file
diff --git a/Utils/RunasAdminOption/NemosMiner.bat b/Utils/RunasAdminOption/NemosMiner.bat
new file mode 100644
index 0000000000..0a297bbbf2
--- /dev/null
+++ b/Utils/RunasAdminOption/NemosMiner.bat
@@ -0,0 +1,44 @@
+@echo off
+:: BatchGotAdmin
+::-------------------------------------
+REM --> Check for permissions
+>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
+
+REM --> If error flag set, we do not have admin.
+if '%errorlevel%' NEQ '0' (
+ echo Requesting administrative privileges...
+ goto UACPrompt
+) else ( goto gotAdmin )
+
+:UACPrompt
+ echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
+ set params = %*:"="
+ echo UAC.ShellExecute "cmd.exe", "/c %~s0 %params%", "", "runas", 1 >> "%temp%\getadmin.vbs"
+
+ "%temp%\getadmin.vbs"
+ del "%temp%\getadmin.vbs"
+ exit /B
+
+:gotAdmin
+ pushd "%CD%"
+ CD /D "%~dp0"
+::--------------------------------------
+
+WHERE /q PWSH.exe
+
+IF ERRORLEVEL 1 (
+
+ echo Powershell 6 or later is required. Cannot continue.
+ pause
+
+) ELSE (
+
+ if not "%GPU_FORCE_64BIT_PTR%"=="1" (setx GPU_FORCE_64BIT_PTR 1) > nul
+ if not "%GPU_MAX_HEAP_SIZE%"=="100" (setx GPU_MAX_HEAP_SIZE 100) > nul
+ if not "%GPU_USE_SYNC_OBJECTS%"=="1" (setx GPU_USE_SYNC_OBJECTS 1) > nul
+ if not "%GPU_MAX_ALLOC_PERCENT%"=="100" (setx GPU_MAX_ALLOC_PERCENT 100) > nul
+ if not "%GPU_SINGLE_ALLOC_PERCENT%"=="100" (setx GPU_SINGLE_ALLOC_PERCENT 100) > nul
+ if not "%CUDA_DEVICE_ORDER%"=="PCI_BUS_ID" (setx CUDA_DEVICE_ORDER PCI_BUS_ID) > nul
+
+ PWSH -executionpolicy bypass -windowstyle maximized -command ".\NemosMiner.ps1 -ConfigFile '.\Config\config.json'"
+)
diff --git a/Utils/SnakeTail.exe b/Utils/SnakeTail.exe
new file mode 100644
index 0000000000..c0faa79ed1
Binary files /dev/null and b/Utils/SnakeTail.exe differ
diff --git a/Utils/Windows10MiningTweaksDmW.bat b/Utils/Windows10MiningTweaksDmW.bat
new file mode 100644
index 0000000000..23f2ac3980
--- /dev/null
+++ b/Utils/Windows10MiningTweaksDmW.bat
@@ -0,0 +1,3070 @@
+rem ========== Pre ==========
+
+rem Don't echo to standard output
+@echo off
+rem Set version info
+set V=5.3.6
+rem Change colors
+color 1F
+rem Set title
+title Windows 10 Mining Tweaks (x64) Version %V% by: DeadManWalking
+
+rem ========== Start ==========
+
+cls
+echo ###############################################################################
+echo # #
+echo # Windows10MiningTweaksDmW Version %V% #
+echo # #
+echo # Microsoft Windows 10 -- Build 10240 (x64) or later #
+echo # #
+echo # AUTHOR: DeadManWalking (DeadManWalkingTO-GitHub) #
+echo # #
+echo # #
+echo # Features #
+echo # #
+echo # 1. System BackUp #
+echo # 1.1. Registry BackUp #
+echo # 1.2. Services BackUp #
+echo # #
+echo # 2. System Tweak #
+echo # 2.1. Registry Tweaks #
+echo # 2.2. Removing Services #
+echo # 2.3. Removing Scheduled Tasks #
+echo # 2.4. Removing Windows Default Apps #
+echo # 2.5. Disable / Remove OneDrive #
+echo # 2.6. Blocking Telemetry Servers #
+echo # 2.7. Blocking More Windows Servers #
+echo # 2.8. Disable Windows Error Recovery on Startup #
+echo # 2.9. Internet Explorer 11 Tweaks #
+echo # 2.10. Libraries Tweaks #
+echo # 2.11. Windows Update Tweaks #
+echo # 2.12. Windows Defender Tweaks #
+echo # #
+echo ###############################################################################
+echo.
+timeout /T 1 /NOBREAK > nul
+
+rem ========== Automatically Check & Get Admin Rights ==========
+
+:init
+setlocal DisableDelayedExpansion
+set "batchPath=%~0"
+for %%k in (%0) do set batchName=%%~nk
+set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
+setlocal EnableDelayedExpansion
+
+:checkPrivileges
+NET FILE 1>nul 2>nul
+if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )
+
+:getPrivileges
+if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges)
+echo.
+echo ###############################################################################
+echo # Invoking UAC for Privilege Escalation #
+echo ###############################################################################
+
+echo Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%"
+echo args = "ELEV " >> "%vbsGetPrivileges%"
+echo For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%"
+echo args = args ^& strArg ^& " " >> "%vbsGetPrivileges%"
+echo Next >> "%vbsGetPrivileges%"
+echo UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%"
+"%SystemRoot%\System32\WScript.exe" "%vbsGetPrivileges%" %*
+exit /B
+
+:gotPrivileges
+setlocal & pushd .
+cd /d %~dp0
+if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul & shift /1)
+
+rem ========== Initializing ==========
+
+setlocal DisableDelayedExpansion
+set "batchPath=%~0"
+for %%k in (%0) do set batchName=%%~nk
+set "vbsServicesBackup=%temp%\DmwServicesBackup_%batchName%.vbs"
+setlocal EnableDelayedExpansion
+
+set "DmwLine= rem By DeadManWalking"
+echo !DmwLine! > %vbsServicesBackup%
+set "DmwLine=Option Explicit"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine=If WScript.Arguments.length = 0 Then"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Dim objShell : Set objShell = CreateObject("Shell.Application")"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= objShell.ShellExecute "wscript.exe", Chr(34) & WScript.ScriptFullName & Chr(34) & " uac", "", "runas", 1"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine=Else"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Dim WshShell, objFSO, strNow, intServiceType, intStartupType, strDisplayName, iSvcCnt"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Dim sREGFile, sBATFile, r, b, strComputer, objWMIService, colListOfServices, objService"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Set WshShell = CreateObject("Wscript.Shell")"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Set objFSO = Wscript.CreateObject("Scripting.FilesystemObject")"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= strNow = Year(Date) & Right("0" & Month(Date), 2) & Right("0" & Day(Date), 2)"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Dim objFile: Set objFile = objFSO.GetFile(WScript.ScriptFullName)"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= sREGFile = "C:\DmWBackup-Services-" & strNow & ".reg""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= sBATFile = "C:\DmWBackup-Services-" & strNow & ".bat""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Set r = objFSO.CreateTextFile (sREGFile, True)"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= r.WriteLine "Windows Registry Editor Version 5.00""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= r.WriteBlankLines 1"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= r.WriteLine ";Services Startup Configuration Backup " & Now"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= r.WriteBlankLines 1"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Set b = objFSO.CreateTextFile (sBATFile, True)"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= b.WriteLine "@echo Restore Service Startup State saved at " & Now"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= b.WriteBlankLines 1"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= strComputer = ".""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= iSvcCnt=0"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Dim sStartState, sSvcName, sSkippedSvc"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Set colListOfServices = objWMIService.ExecQuery ("Select * from Win32_Service")"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= For Each objService In colListOfServices"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= iSvcCnt=iSvcCnt + 1"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= r.WriteLine "[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\" & trim(objService.Name) & "]""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= sStartState = lcase(objService.StartMode)"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= sSvcName = objService.Name"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Select Case sStartState"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Case "boot""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= r.WriteLine chr(34) & "Start" & Chr(34) & "=dword:00000000""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= b.WriteLine "sc.exe config " & sSvcName & " start= boot""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Case "system""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= r.WriteLine chr(34) & "Start" & Chr(34) & "=dword:00000001""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= b.WriteLine "sc.exe config " & sSvcName & " start= system""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Case "auto""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= r.WriteLine chr(34) & "Start" & Chr(34) & "=dword:00000002""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= If objService.DelayedAutoStart = True Then"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= r.WriteLine chr(34) & "DelayedAutostart" & Chr(34) & "=dword:00000001""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= b.WriteLine "sc.exe config " & sSvcName & " start= delayed-auto""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Else"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= r.WriteLine chr(34) & "DelayedAutostart" & Chr(34) & "=-""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= b.WriteLine "sc.exe config " & sSvcName & " start= auto""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= End If"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Case "manual""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= r.WriteLine chr(34) & "Start" & Chr(34) & "=dword:00000003""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= b.WriteLine "sc.exe config " & sSvcName & " start= demand""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Case "disabled""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= r.WriteLine chr(34) & "Start" & Chr(34) & "=dword:00000004""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= b.WriteLine "sc.exe config " & sSvcName & " start= disabled""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Case "unknown" sSkippedSvc = sSkippedSvc & ", " & sSvcName"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= End Select"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= r.WriteBlankLines 1"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Next"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= If trim(sSkippedSvc) <> "" Then"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= WScript.Echo iSvcCnt & " Services found. The services " & sSkippedSvc & " could not be backed up.""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Else"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= WScript.Echo iSvcCnt & " Services found and their startup configuration backed up.""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= End If"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= r.Close"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= b.WriteLine "@pause""
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= b.Close"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Set objFSO = Nothing"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine= Set WshShell = Nothing"
+echo !DmwLine! >> %vbsServicesBackup%
+set "DmwLine=End If"
+echo !DmwLine! >> %vbsServicesBackup%
+
+set "DmwBackupFilename=C:\DmWBackup"
+set DmwDate=%date:~10,4%%date:~7,2%%date:~4,2%
+
+set PMax=0
+set PRun=0
+set PAct=0
+
+rem ========== 1. System BackUp ==========
+
+echo.
+echo ###############################################################################
+echo # 1. System BackUp -- Start #
+echo ###############################################################################
+echo.
+
+rem ========== 1.1. Registry BackUp ==========
+
+echo.
+echo ###############################################################################
+echo # 1.1. Registry BackUp -- Start #
+echo ###############################################################################
+echo.
+
+:500
+set /A Pline=500
+set PMax=5
+set PRun=0
+rem set PAct=0
+echo Registry BackUp in C:\ (%PMax%).
+set /p Pselect="Continue? y/n/a: "
+if '%Pselect%' == 'y' set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+2
+if '%Pselect%' == 'n' set /A Pline=%Pline%+100
+goto %Pline%
+
+:501
+set myMSG=BackUp HKCR (HKEY_CLASSES_ROOT)
+echo %myMSG%
+set myMSG=Describes file type, file extension, and OLE information.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:502
+reg EXPORT HKCR %DmwBackupFilename%-Reg-HKCR-%DmwDate%.reg /y
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry BackUp. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:503
+set myMSG=BackUp HKCU (HKEY_CURRENT_USER)
+echo %myMSG%
+set myMSG=Contains user who is currently logged into Windows and their settings.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:504
+reg EXPORT HKCU %DmwBackupFilename%-Reg-HKCU-%DmwDate%.reg /y
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry BackUp. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:505
+set myMSG=BackUp HKLM (HKEY_LOCAL_MACHINE)
+echo %myMSG%
+set myMSG=Contains computer-specific information about the hardware installed, software settings, and other information. The information is used for all users who log on to that computer and is one of the more commonly accessed areas in the registry.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:506
+reg EXPORT HKLM %DmwBackupFilename%-Reg-HKLM-%DmwDate%.reg /y
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry BackUp. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:507
+set myMSG=BackUp HKU (HKEY_USERS)
+echo %myMSG%
+set myMSG=Contains information about all the users who log on to the computer, including both generic and user-specific information.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:508
+reg EXPORT HKU %DmwBackupFilename%-Reg-HKU-%DmwDate%.reg /y
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry BackUp. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:509
+set myMSG=BackUp HKCC (HKEY_CURRENT_CONFIG)
+echo %myMSG%
+set myMSG=The details about the current configuration of hardware attached to the computer.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:510
+reg EXPORT HKCC %DmwBackupFilename%-Reg-HKCC-%DmwDate%.reg /y
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry BackUp. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:511
+:512
+
+:599
+echo.
+echo ###############################################################################
+echo # 1.1. Registry BackUp -- End #
+echo ###############################################################################
+echo.
+
+rem ========== 1.2. Services BackUp ==========
+
+echo.
+echo ###############################################################################
+echo # 1.2. Services BackUp -- Start #
+echo ###############################################################################
+echo.
+
+:600
+set /A Pline=600
+set PMax=1
+set PRun=0
+rem set PAct=0
+echo Registry BackUp in C:\ (%PMax%).
+set /p Pselect="Continue? y/n/a: "
+if '%Pselect%' == 'y' set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+2
+if '%Pselect%' == 'n' set /A Pline=%Pline%+100
+goto %Pline%
+
+:601
+set myMSG=Queries the list of Windows services and their startup type configuration.
+echo %myMSG%
+set myMSG=The results are written to .reg and .bat files for later restoration. The two files are created in the C:\ folder.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:602
+WScript.exe %vbsServicesBackup%
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry BackUp. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:603
+:604
+
+:649
+echo.
+echo ###############################################################################
+echo # 1.2. Services BackUp -- End #
+echo ###############################################################################
+echo.
+
+rem ========== 2. System BackUp ==========
+
+echo.
+echo ###############################################################################
+echo # 2. System Tweaks -- Start #
+echo ###############################################################################
+echo.
+
+rem ========== 2.1. Registry Tweaks ==========
+
+echo.
+echo ###############################################################################
+echo # 2.1. Registry Tweaks -- Start #
+echo ###############################################################################
+echo.
+
+:1000
+set /A Pline=1000
+set PMax=37
+set PRun=0
+rem set PAct=0
+echo Apply Registry tweaks (%PMax%).
+set /p Pselect="Continue? y/n/a: "
+if '%Pselect%' == 'y' set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+2
+if '%Pselect%' == 'n' set /A Pline=%Pline%+100
+goto %Pline%
+
+:1001
+set myMSG=Show computer shortcut on desktop.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1002
+rem 0 = show icon, 1 = don't show icon
+reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel" /v "{20D04FE0-3AEA-1069-A2D8-08002B30309D}" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1003
+set myMSG=Show Network shortcut on desktop.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1004
+rem 0 = show icon, 1 = don't show icon
+reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel" /v "{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1005
+set myMSG=Classic vertical icon spacing.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1006
+reg add "HKCU\Control Panel\Desktop\WindowMetrics" /v "IconVerticalSpacing" /t REG_SZ /d "-1150" /f > nul 2>&1set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1007
+set myMSG=Lock the Taskbar.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1008
+reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "TaskbarSizeMove" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1009
+set myMSG=Always show all icons on the taskbar (next to clock).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1010
+rem 0 = Show all icons
+rem 1 = Hide icons on the taskbar
+reg add "HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer" /v "EnableAutoTray" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1011
+set myMSG=Delay taskbar thumbnail pop-ups to 10 seconds.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1012
+reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "ExtendedUIHoverTime" /t REG_DWORD /d "10000" /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1013
+set myMSG=Enable classic control panel view.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1014
+reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" /v "ForceClassicControlPanel" /t REG_DWORD /d 1 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1015
+set myMSG=Turn OFF Sticky Keys when SHIFT is pressed 5 times.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1016
+rem 506 = Off, 510 = On (default)
+reg add "HKCU\Control Panel\Accessibility\StickyKeys" /v "Flags" /t REG_SZ /d "506" /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1017
+set myMSG=Turn OFF Filter Keys when SHIFT is pressed for 8 seconds.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1018
+rem 122 = Off, 126 = On (default)
+reg add "HKCU\Control Panel\Accessibility\Keyboard Response" /v "Flags" /t REG_SZ /d "122" /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1019
+set myMSG=Disable Hibernation.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1020
+reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Power" /v "HiberbootEnabled" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1021
+set myMSG=Underline keyboard shortcuts and access keys.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1022
+reg add "HKCU\Control Panel\Accessibility\Keyboard Preference" /v "On" /t REG_SZ /d 1 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1023
+set myMSG=Show known file extensions in Explorer.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1024
+rem 0 = extensions are visible
+rem 1 = extensions are hidden
+reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "HideFileExt" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1025
+set myMSG=Hide indication for compressed NTFS files.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1026
+reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "ShowCompColor" /t RED_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1027
+set myMSG=Show Hidden files in Explorer.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1028
+reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "Hidden" /t REG_DWORD /d 1 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1029
+set myMSG=Show Super Hidden System files in Explorer.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1030
+reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "ShowSuperHidden" /t REG_DWORD /d 1 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1031
+set myMSG=Prevent both Windows and Office from creating LNK files in the Recents folder.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1032
+reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" /v "NoRecentDocsHistory" /t REG_DWORD /d 1 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1033
+set myMSG=Replace Utilman with CMD.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1034
+reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\utilman.exe" /v "Debugger" /t REG_SZ /d "cmd.exe" /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1035
+set myMSG=Add the option "Processor performance core parking min cores".
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1036
+rem Option will be added to: Power Options > High Performance > Change Plan Settings > Change advanced power settings > Processor power management
+rem Default data is 1 (option hidden)
+reg add "HKLM\SYSTEM\CurrentControlSet\Control\Power\PowerSettings\54533251-82be-4824-96c1-47b60b740d00\0cc5b647-c1df-4637-891a-dec35c318583" /v "Attributes" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1037
+set myMSG=Add the option "Disable CPU Core Parking".
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1038
+rem Default value is 100 decimal.
+rem Basically "Core parking" means that the OS can use less CPU cores when they are not needed, and saving power.
+rem This, however, can somewhat hamper performance, so advanced users prefer to disable this feature.
+reg add "HKLM\SYSTEM\CurrentControlSet\Control\Power\PowerSettings\54533251-82be-4824-96c1-47b60b740d00\0cc5b647-c1df-4637-891a-dec35c318583" /v "ValueMax" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1039
+set myMSG=Remove Logon screen wallpaper/background. Will use solid color instead (Accent color).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1040
+reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\System" /v "DisableLogonBackgroundImage" /t REG_DWORD /d 1 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1041
+set myMSG=Disable lockscreen.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1042
+reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\Personalization" /v "NoLockScreen" /t REG_DWORD /d 1 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1043
+set myMSG=Remove versioning tab from properties.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1044
+reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer" /v NoPreviousVersionsPage /t REG_DWORD /d 1 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1045
+set myMSG=Disable jump lists.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1046
+reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "Start_TrackDocs" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1047
+set myMSG=Disable Windows Error Reporting.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1048
+reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\Windows Error Reporting" /v "Disabled" /t REG_DWORD /d 1 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1049
+set myMSG=Disable Cortana (Speech Search Assistant, which also sends information to Microsoft).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1050
+reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\Windows Search" /v "AllowCortana" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1051
+set myMSG=Hide the search box from taskbar. You can still search by pressing the Win key and start typing what you're looking for.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1052
+reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Search" /v "SearchboxTaskbarMode" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1053
+set myMSG=Disable MRU lists (jump lists) of XAML apps in Start Menu.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1054
+reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "Start_TrackDocs" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1055
+set myMSG=Set Windows Explorer to start on This PC instead of Quick Access.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1056
+rem 1 = This PC, 2 = Quick access
+reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "LaunchTo" /t REG_DWORD /d 1 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1057
+set myMSG=Disable Disk Quota tab, which appears as a tab when right-clicking on drive letter - Properties.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1058
+rem 1 = This PC, 2 = Quick access
+reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\DiskQuota" /v "Enable" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1059
+set myMSG=Disable creation of an Advertising ID.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1060
+rem 1 = This PC, 2 = Quick access
+reg add "HKLM\Software\Microsoft\Windows\CurrentVersion\AdvertisingInfo" /v "Enabled" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1061
+set myMSG=Remove Pin to start (3).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1062
+reg delete "HKEY_CLASSES_ROOT\exefile\shellex\ContextMenuHandlers\PintoStartScreen" /f > nul 2>&1
+reg delete "HKEY_CLASSES_ROOT\Folder\shellex\ContextMenuHandlers\PintoStartScreen" /f > nul 2>&1
+reg delete "HKEY_CLASSES_ROOT\mscfile\shellex\ContextMenuHandlers\PintoStartScreen" /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+3
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1063
+set myMSG=Disable Cortana, Bing Search and Searchbar (4).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1064
+reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\Windows Search" /v "AllowCortana" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Search" /v "CortanaEnabled" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Search" /v "SearchboxTaskbarMode" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Search" /v "BingSearchEnabled" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+4
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1065
+set myMSG=Turn off the Error Dialog (2).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1066
+reg add "HKCU\SOFTWARE\Microsoft\Windows\Windows Error Reporting" /v "DontShowUI" /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting" /v "DontShowUI" /t REG_DWORD /d 1 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+2
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1067
+set myMSG=Disable Administrative shares (2).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1068
+reg add "HKLM\System\CurrentControlSet\Services\LanmanServer\Parameters" /v "AutoShareWks" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKLM\System\CurrentControlSet\Services\LanmanServer\Parameters" /v "AutoShareServer" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+2
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1069
+set myMSG=Add "Reboot to Recovery" to right-click menu of "This PC" (4).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1070
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\shell" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\shell" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg add "HKEY_CLASSES_ROOT\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\shell\Reboot to Recovery" /v "Icon" /t REG_SZ /d %SystemRoot%\System32\imageres.dll,-110" /f > nul 2>&1
+reg add "HKEY_CLASSES_ROOT\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\shell\Reboot to Recovery\command" /ve /d "shutdown.exe -r -o -f -t 00" /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+4
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1071
+set myMSG=Change Clock and Date formats of current user to: 24H, metric (Sign out required to see changes) (6).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1072
+rem Apply to all users by using the key: HKLM\SYSTEM\CurrentControlSet\Control\CommonGlobUserSettings\Control Panel\International
+reg add "HKCU\Control Panel\International" /v "iMeasure" /t REG_SZ /d "0" /f > nul 2>&1
+reg add "HKCU\Control Panel\International" /v "iNegCurr" /t REG_SZ /d "1" /f > nul 2>&1
+reg add "HKCU\Control Panel\International" /v "iTime" /t REG_SZ /d "1" /f > nul 2>&1
+reg add "HKCU\Control Panel\International" /v "sShortDate" /t REG_SZ /d "yyyy/MM/dd" /f > nul 2>&1
+reg add "HKCU\Control Panel\International" /v "sShortTime" /t REG_SZ /d "HH:mm" /f > nul 2>&1
+reg add "HKCU\Control Panel\International" /v "sTimeFormat" /t REG_SZ /d "H:mm:ss" /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+6
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1073
+set myMSG=Enable Developer Mode (enables you to run XAML apps you develop in Visual Studio which haven't been certified yet) (2).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1074
+reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" /v "AllowAllTrustedApps" /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" /v "AllowDevelopmentWithoutDevLicense" /t REG_DWORD /d 1 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+2
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1075
+set myMSG=Remove telemetry and data collection (14).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:1076
+reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Device Metadata" /v PreventDeviceMetadataFromNetwork /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection" /v "AllowTelemetry" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKLM\SOFTWARE\Policies\Microsoft\MRT" /v DontOfferThroughWUAU /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKLM\SOFTWARE\Policies\Microsoft\SQMClient\Windows" /v "CEIPEnable" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\AppCompat" /v "AITEnable" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\AppCompat" /v "DisableUAR" /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\DataCollection" /v "AllowTelemetry" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKLM\COMPONENTS\DerivedData\Components\amd64_microsoft-windows-c..lemetry.lib.cortana_31bf3856ad364e35_10.0.10240.16384_none_40ba2ec3d03bceb0" /v "f!dss-winrt-telemetry.js" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKLM\COMPONENTS\DerivedData\Components\amd64_microsoft-windows-c..lemetry.lib.cortana_31bf3856ad364e35_10.0.10240.16384_none_40ba2ec3d03bceb0" /v "f!proactive-telemetry.js" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKLM\COMPONENTS\DerivedData\Components\amd64_microsoft-windows-c..lemetry.lib.cortana_31bf3856ad364e35_10.0.10240.16384_none_40ba2ec3d03bceb0" /v "f!proactive-telemetry-event_8ac43a41e5030538" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKLM\COMPONENTS\DerivedData\Components\amd64_microsoft-windows-c..lemetry.lib.cortana_31bf3856ad364e35_10.0.10240.16384_none_40ba2ec3d03bceb0" /v "f!proactive-telemetry-inter_58073761d33f144b" /t REG_DWORD /d 0 /f > nul 2>&1
+
+reg add "HKLM\SYSTEM\CurrentControlSet\Control\WMI\AutoLogger\AutoLogger-Diagtrack-Listener" /v "Start" /t REG_DWORD /d 0 /f
+reg add "HKLM\SYSTEM\CurrentControlSet\Control\WMI\AutoLogger\SQMLogger" /v "Start" /t REG_DWORD /d 0 /f
+reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Channels\Microsoft-Windows-Application-Experience/Program-Telemetry" /v "Enabled" /t REG_DWORD /d 0 /f
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+2
+echo Done %PRun% / %PMax% Registry Tweaks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:1077
+:1078
+
+:1100
+echo.
+echo ###############################################################################
+echo # 2.1. Registry Tweaks -- End #
+echo ###############################################################################
+echo.
+
+rem ========== 2.2. Removing Services ==========
+
+echo.
+echo ###############################################################################
+echo # 2.2. Removing Services -- Start #
+echo ###############################################################################
+echo.
+
+:2000
+set /A Pline=2000
+set PMax=36
+set PRun=0
+rem set PAct=0
+echo Removing Services (%PMax%).
+set /p Pselect="Continue? y/n/a: "
+if '%Pselect%' == 'y' set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+2
+if '%Pselect%' == 'n' set /A Pline=%Pline%+100
+goto %Pline%
+
+:2001
+set myMSG=Disable Connected User Experiences and Telemetry (To turn off Telemetry and Data Collection).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2002
+sc config DiagTrack start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2003
+set myMSG=Disable Diagnostic Policy Service.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2004
+sc config DPS start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2005
+set myMSG=Disable Distributed Link Tracking Client (If your computer is not connected to any network).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2006
+sc config TrkWks start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2007
+set myMSG=Disable WAP Push Message Routing Service (To turn off Telemetry and Data Collection).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2008
+sc config dmwappushservice start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2009
+set myMSG=Disable Downloaded Maps Manager (If you don't use Maps app).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2010
+sc config MapsBroker start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2011
+set myMSG=Disable IP Helper (If you don't use IPv6 connection).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2012
+sc config iphlpsvc start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2013
+set myMSG=Disable Program Compatibility Assistant Service.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2014
+sc config PcaSvc start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2015
+set myMSG=Disable Print Spooler (If you don't have a printer).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2016
+sc config Spooler start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2017
+set myMSG=Disable Remote Registry (You can set it to DISABLED for Security purposes).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2018
+sc config RemoteRegistry start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2019
+set myMSG=Disable Secondary Logon.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2020
+sc config seclogon start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2021
+set myMSG=Disable Security Center.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2022
+sc config wscsvc start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2023
+set myMSG=Disable TCP/IP NetBIOS Helper (If you are not in a workgroup network).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2024
+sc config lmhosts start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2025
+set myMSG=Disable Touch Keyboard and Handwriting Panel Service (If you don't want to use touch keyboard and handwriting features.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2026
+sc config TabletInputService start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2027
+set myMSG=Disable Windows Error Reporting Service.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2028
+sc config WerSvc start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2029
+set myMSG=Disable Windows Image Acquisition (WIA) (If you don't have a scanner).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2030
+sc config stisvc start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2031
+set myMSG=Disable Windows Search.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2032
+sc config WSearch start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2033
+set myMSG=Disable tracking services (2).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2034
+sc config diagnosticshub.standardcollector.service start= Disabled > nul 2>&1
+sc config WMPNetworkSvc start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+2
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2035
+set myMSG=Disable Superfetch.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2036
+sc config SysMain start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2037
+set myMSG=Disable Xbox Services (5).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2038
+rem Xbox Accessory Management Service
+sc config XboxGipSvc start= Disabled > nul 2>&1
+rem Xbox Game Monitoring
+sc config xbgm start= Disabled > nul 2>&1
+rem Xbox Live Auth Manager
+sc config XblAuthManager start= Disabled > nul 2>&1
+rem Xbox Live Game Save
+sc config XblGameSave start= Disabled > nul 2>&1
+rem Xbox Live Networking Service
+sc config XboxNetApiSvc start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+5
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2039
+set myMSG=Disable AllJoyn Router Service.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2040
+rem This service is used for routing the AllJoyn messages for AllJoyn clients.
+sc config AJRouter start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2041
+set myMSG=Disable Bluetooth Services (2).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2042
+rem Bluetooth Handsfree Service
+sc config BthHFSrv start= Disabled > nul 2>&1
+rem Bluetooth Support Service
+sc config bthserv start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+2
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2043
+set myMSG=Disable Geolocation Service.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2044
+sc config lfsvc start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2045
+set myMSG=Disable Phone Service.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2046
+sc config PhoneSvc start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2047
+set myMSG=Disable Windows Biometric Service.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2048
+sc config WbioSrvc start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2049
+set myMSG=Disable Windows Mobile Hotspot Service.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2050
+sc config icssvc start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2051
+set myMSG=Disable Windows Media Player Network Sharing Service.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2052
+sc config WMPNetworkSvc start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2053
+set myMSG=Disable Windows Update Service.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2054
+sc config wuauserv start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2055
+set myMSG=Disable Enterprise App Management Service.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2056
+sc config EntAppSvc start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2057
+set myMSG=Disable Hyper-V Services (9).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2058
+rem HV Host Service
+sc config HvHost start= Disabled > nul 2>&1
+rem Hyper-V Data Exchange Service
+sc config vmickvpexchange start= Disabled > nul 2>&1
+rem Hyper-V Guest Service Interface
+sc config vmicguestinterface start= Disabled > nul 2>&1
+rem Hyper-V Guest Shutdown Service
+sc config vmicshutdown start= Disabled > nul 2>&1
+rem Hyper-V Heartbeat Service
+sc config vmicheartbeat start= Disabled > nul 2>&1
+rem Hyper-V PowerShell Direct Service
+sc config vmicvmsession start= Disabled > nul 2>&1
+rem Hyper-V Remote Desktop Virtualization Service
+sc config vmicrdv start= Disabled > nul 2>&1
+rem Hyper-V Time Synchronization Service
+sc config vmictimesync start= Disabled > nul 2>&1
+rem Hyper-V Volume Shadow Copy Requestor
+sc config vmicvss start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+9
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2059
+set myMSG=Disable HomeGroup Listener.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2060
+sc config HomeGroupListener start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2061
+set myMSG=Disable HomeGroup Provider.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2062
+sc config HomeGroupProvider start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2063
+set myMSG=Disable Net.Tcp Port Sharing Service.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2064
+sc config NetTcpPortSharing start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2065
+set myMSG=Disable Routing and Remote Access.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2066
+sc config RemoteAccess start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2067
+set myMSG=Disable Internet Connection Sharing (ICS).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2068
+sc config RemoteAccess start= Disabled > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2069
+set myMSG=Disable Superfetch (A must for SSD drives, but good to do in general)(3).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2070
+rem Disabling this service prevents further creation of PF files in C:\Windows\Prefetch.
+rem After disabling this service, it is completely safe to delete everything in that folder, except for the ReadyBoot folder.
+sc config SysMain start= disabled
+reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters" /v "EnableSuperfetch" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters" /v "EnablePrefetcher" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+3
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2071
+set myMSG=Disable Action Center & Security Center.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:2072
+reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\ImmersiveShell" /v "UseActionCenterExperience" /t REG_DWORD /d 0 /f
+sc config wscsvc start= disabled
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+2
+echo Done %PRun% / %PMax% Services Remove. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:2073
+:2074
+
+:2100
+echo.
+echo ###############################################################################
+echo # 2.2. Removing Services -- End #
+echo ###############################################################################
+echo.
+
+rem ========== 2.3. Removing Scheduled Tasks ==========
+
+echo.
+echo ###############################################################################
+echo # 2.3. Removing Scheduled Tasks -- Start #
+echo ###############################################################################
+echo.
+
+:3000
+set /A Pline=3000
+set PMax=1
+set PRun=0
+rem set PAct=0
+echo Removing scheduled tasks (17).
+set /p Pselect="Continue? y/n: "
+if '%Pselect%' == 'y' set /A Pline=%Pline%+1
+if '%Pselect%' == 'n' set /A Pline=%Pline%+100
+goto %Pline%
+
+:3001
+schtasks /Change /TN "Microsoft\Windows\AppID\SmartScreenSpecific" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\Application Experience\ProgramDataUpdater" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\Application Experience\StartupAppTask" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\Autochk\Proxy" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\Customer Experience Improvement Program\Consolidator" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\Customer Experience Improvement Program\KernelCeipTask" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\Customer Experience Improvement Program\UsbCeip" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\DiskDiagnostic\Microsoft-Windows-DiskDiagnosticDataCollector" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\FileHistory\File History (maintenance mode)" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\Maintenance\WinSAT" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\NetTrace\GatherNetworkInfo" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\PI\Sqm-Tasks" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\Time Synchronization\ForceSynchronizeTime" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\Time Synchronization\SynchronizeTime" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\Windows Error Reporting\QueueReporting" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\WindowsUpdate\Automatic App Update" /Disable > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+17
+echo Done %PRun% / %PMax% Removing Scheduled Tasks. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+
+:3100
+echo.
+echo ###############################################################################
+echo # 2.3. Removing Scheduled Tasks -- End #
+echo ###############################################################################
+echo.
+
+rem ========== 2.4. Removing Windows Default Apps ==========
+
+echo.
+echo ###############################################################################
+echo # 2.4. Removing Windows Default Apps -- Start #
+echo ###############################################################################
+echo.
+
+:4000
+set /A Pline=4000
+set PMax=1
+set PRun=0
+rem set PAct=0
+echo Removing Windows default apps (12).
+set /p Pselect="Continue? y/n: "
+if '%Pselect%' == 'y' set /A Pline=%Pline%+1
+if '%Pselect%' == 'n' set /A Pline=%Pline%+100
+goto %Pline%
+
+:4001
+powershell "Get-AppxPackage *3d* | Remove-AppxPackage" > nul 2>&1
+powershell "Get-AppxPackage *bing* | Remove-AppxPackage" > nul 2>&1
+powershell "Get-AppxPackage *zune* | Remove-AppxPackage" > nul 2>&1
+powershell "Get-AppxPackage *photo* | Remove-AppxPackage" > nul 2>&1
+powershell "Get-AppxPackage *communi* | Remove-AppxPackage" > nul 2>&1
+powershell "Get-AppxPackage *solit* | Remove-AppxPackage" > nul 2>&1
+powershell "Get-AppxPackage *phone* | Remove-AppxPackage" > nul 2>&1
+powershell "Get-AppxPackage *soundrec* | Remove-AppxPackage" > nul 2>&1
+powershell "Get-AppxPackage *camera* | Remove-AppxPackage" > nul 2>&1
+powershell "Get-AppxPackage *people* | Remove-AppxPackage" > nul 2>&1
+powershell "Get-AppxPackage *office* | Remove-AppxPackage" > nul 2>&1
+powershell "Get-AppxPackage *xbox* | Remove-AppxPackage" > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+12
+echo Done %PRun% / %PMax% Removing Windows Default Apps. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+
+:4100
+echo.
+echo ###############################################################################
+echo # 2.4. Removing Windows Default Apps -- End #
+echo ###############################################################################
+echo.
+
+rem ========== 2.5. Disable / Remove OneDrive ==========
+
+echo.
+echo ###############################################################################
+echo # 2.5. Disable / Remove OneDrive -- Start #
+echo ###############################################################################
+echo.
+
+:5000
+set /A Pline=5000
+set PMax=1
+set PRun=0
+rem set PAct=0
+echo Disable OneDrive (7).
+set /p Pselect="Continue? y/n: "
+if '%Pselect%' == 'y' set /A Pline=%Pline%+1
+if '%Pselect%' == 'n' set /A Pline=%Pline%+100
+goto %Pline%
+
+:5001
+reg add "HKLM\Software\Policies\Microsoft\Windows\OneDrive" /v DisableFileSyncNGSC /t REG_DWORD /d 1 /f > nul 2>&1
+
+reg delete "HKEY_CLASSES_ROOT\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" /f > nul 2>&1
+reg delete "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" /f > nul 2>&1
+reg delete "HKCU\SOFTWARE\Classes\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" /f > nul 2>&1
+reg delete "HKCU\SOFTWARE\Classes\Wow6432Node\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" /f > nul 2>&1
+
+:: Detete OneDrive icon on explorer.exe (Only 64 Bits)
+reg add "HKEY_CLASSES_ROOT\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" /v System.IsPinnedToNameSpaceTree /t reg_DWORD /d 0 /f > nul 2>&1
+reg add "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" /v System.IsPinnedToNameSpaceTree /t reg_DWORD /d 0 /f > nul 2>&1
+
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+7
+echo Done %PRun% / %PMax% Disable / Remove OneDrive. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+
+:5100
+echo.
+echo ###############################################################################
+echo # 2.5. Disable / Remove OneDrive -- End #
+echo ###############################################################################
+echo.
+
+rem ========== 6. Blocking Telemetry Servers ==========
+
+echo.
+echo ###############################################################################
+echo # 2.6. Blocking Telemetry Servers -- Start #
+echo ###############################################################################
+echo.
+
+:6000
+set /A Pline=6000
+set PMax=1
+set PRun=0
+rem set PAct=0
+echo Blocking Telemetry Servers (25).
+set /p Pselect="Continue? y/n: "
+if '%Pselect%' == 'y' set /A Pline=%Pline%+1
+if '%Pselect%' == 'n' set /A Pline=%Pline%+100
+goto %Pline%
+
+:6001
+copy "%WINDIR%\system32\drivers\etc\hosts" "%WINDIR%\system32\drivers\etc\hosts.bak" > nul 2>&1
+attrib -r "%WINDIR%\system32\drivers\etc\hosts" > nul 2>&1
+find /C /I "choice.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 choice.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "choice.microsoft.com.nsatc.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 choice.microsoft.com.nsatc.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "df.telemetry.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 df.telemetry.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "oca.telemetry.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 oca.telemetry.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "oca.telemetry.microsoft.com.nsatc.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 oca.telemetry.microsoft.com.nsatc.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "redir.metaservices.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 redir.metaservices.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "reports.wes.df.telemetry.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 reports.wes.df.telemetry.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "services.wes.df.telemetry.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 services.wes.df.telemetry.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "settings-sandbox.data.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 settings-sandbox.data.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "sqm.df.telemetry.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 sqm.df.telemetry.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "sqm.telemetry.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 sqm.telemetry.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "sqm.telemetry.microsoft.com.nsatc.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 sqm.telemetry.microsoft.com.nsatc.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "telecommand.telemetry.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 telecommand.telemetry.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "telecommand.telemetry.microsoft.com.nsatc.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 telecommand.telemetry.microsoft.com.nsatc.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "telemetry.appex.bing.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 telemetry.appex.bing.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "telemetry.appex.bing.net:443" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 telemetry.appex.bing.net:443>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "telemetry.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 telemetry.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "telemetry.urs.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 telemetry.urs.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "vortex.data.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 vortex.data.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "vortex-sandbox.data.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 vortex-sandbox.data.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "vortex-win.data.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 vortex-win.data.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "watson.ppe.telemetry.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 watson.ppe.telemetry.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "watson.telemetry.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 watson.telemetry.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "watson.telemetry.microsoft.com.nsatc.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 watson.telemetry.microsoft.com.nsatc.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "wes.df.telemetry.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 wes.df.telemetry.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+attrib +r "%WINDIR%\system32\drivers\etc\hosts" > nul 2>&1
+
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+25
+echo Done %PRun% / %PMax% Blocking Telemetry Servers. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+
+:6100
+echo.
+echo ###############################################################################
+echo # 2.6. Blocking Telemetry Servers -- End #
+echo ###############################################################################
+echo.
+
+rem ========== 2.7. Blocking More Windows Servers ==========
+
+echo.
+echo ###############################################################################
+echo # 2.7. Blocking More Windows Servers -- Start #
+echo ###############################################################################
+echo.
+
+:7000
+set /A Pline=7000
+set PMax=1
+set PRun=0
+rem set PAct=0
+echo Blocking More Telemetry Servers (109).
+set /p Pselect="Continue? y/n: "
+if '%Pselect%' == 'y' set /A Pline=%Pline%+1
+if '%Pselect%' == 'n' set /A Pline=%Pline%+100
+goto %Pline%
+
+:7001
+copy "%WINDIR%\system32\drivers\etc\hosts" "%WINDIR%\system32\drivers\etc\hosts.bak" > nul 2>&1
+attrib -r "%WINDIR%\system32\drivers\etc\hosts" > nul 2>&1
+find /C /I "184-86-53-99.deploy.static.akamaitechnologies.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 184-86-53-99.deploy.static.akamaitechnologies.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a.ads1.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a.ads1.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a.ads2.msads.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a.ads2.msads.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a.ads2.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a.ads2.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a.rad.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a.rad.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a-0001.a-msedge.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a-0001.a-msedge.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a-0002.a-msedge.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a-0002.a-msedge.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a-0003.a-msedge.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a-0003.a-msedge.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a-0004.a-msedge.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a-0004.a-msedge.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a-0005.a-msedge.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a-0005.a-msedge.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a-0006.a-msedge.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a-0006.a-msedge.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a-0007.a-msedge.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a-0007.a-msedge.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a-0008.a-msedge.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a-0008.a-msedge.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a-0009.a-msedge.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a-0009.a-msedge.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a1621.g.akamai.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a1621.g.akamai.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a1856.g2.akamai.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a1856.g2.akamai.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a1961.g.akamai.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a1961.g.akamai.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a978.i6g1.akamai.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a978.i6g1.akamai.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "ac3.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 ac3.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "ad.doubleclick.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 ad.doubleclick.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "adnexus.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 adnexus.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "adnxs.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 adnxs.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "ads.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 ads.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "ads1.msads.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 ads1.msads.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "ads1.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 ads1.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "aidps.atdmt.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 aidps.atdmt.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "aka-cdn-ns.adtech.de" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 aka-cdn-ns.adtech.de>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a-msedge.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a-msedge.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "any.edge.bing.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 any.edge.bing.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "az361816.vo.msecnd.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 az361816.vo.msecnd.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "az512334.vo.msecnd.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 az512334.vo.msecnd.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "b.ads1.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 b.ads1.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "b.ads2.msads.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 b.ads2.msads.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "b.rad.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 b.rad.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "bingads.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 bingads.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "bs.serving-sys.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 bs.serving-sys.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "c.atdmt.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 c.atdmt.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "cdn.atdmt.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 cdn.atdmt.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "cds26.ams9.msecn.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 cds26.ams9.msecn.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "compatexchange.cloudapp.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 compatexchange.cloudapp.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "corp.sts.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 corp.sts.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "corpext.msitadfs.glbdns2.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 corpext.msitadfs.glbdns2.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "cs1.wpc.v0cdn.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 cs1.wpc.v0cdn.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "cy2.vortex.data.microsoft.com.akadns.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 cy2.vortex.data.microsoft.com.akadns.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "db3aqu.atdmt.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 db3aqu.atdmt.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "diagnostics.support.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 diagnostics.support.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "e2835.dspb.akamaiedge.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 e2835.dspb.akamaiedge.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "e7341.g.akamaiedge.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 e7341.g.akamaiedge.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "e7502.ce.akamaiedge.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 e7502.ce.akamaiedge.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "e8218.ce.akamaiedge.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 e8218.ce.akamaiedge.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "ec.atdmt.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 ec.atdmt.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "fe2.update.microsoft.com.akadns.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 fe2.update.microsoft.com.akadns.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "fe2.update.microsoft.com.akadns.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 fe2.update.microsoft.com.akadns.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "feedback.microsoft-hohm.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 feedback.microsoft-hohm.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "feedback.search.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 feedback.search.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "feedback.windows.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 feedback.windows.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "flex.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 flex.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "g.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 g.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "h1.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 h1.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "h2.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 h2.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "hostedocsp.globalsign.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 hostedocsp.globalsign.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "i1.services.social.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 i1.services.social.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "i1.services.social.microsoft.com.nsatc.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 i1.services.social.microsoft.com.nsatc.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "ipv6.msftncsi.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 ipv6.msftncsi.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "ipv6.msftncsi.com.edgesuite.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 ipv6.msftncsi.com.edgesuite.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "lb1.www.ms.akadns.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 lb1.www.ms.akadns.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "live.rads.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 live.rads.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "m.adnxs.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 m.adnxs.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "m.hotmail.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 m.hotmail.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "msedge.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 msedge.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "msftncsi.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 msftncsi.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "msnbot-65-55-108-23.search.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 msnbot-65-55-108-23.search.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "msntest.serving-sys.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 msntest.serving-sys.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "onesettings-db5.metron.live.nsatc.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 onesettings-db5.metron.live.nsatc.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "pre.footprintpredict.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 pre.footprintpredict.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "preview.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 preview.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "rad.live.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 rad.live.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "rad.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 rad.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "s0.2mdn.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 s0.2mdn.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "schemas.microsoft.akadns.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 schemas.microsoft.akadns.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "secure.adnxs.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 secure.adnxs.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "secure.flashtalking.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 secure.flashtalking.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "settings-win.data.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 settings-win.data.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "sls.update.microsoft.com.akadns.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 sls.update.microsoft.com.akadns.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "ssw.live.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 ssw.live.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "static.2mdn.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 static.2mdn.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "statsfe1.ws.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 statsfe1.ws.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "statsfe2.update.microsoft.com.akadns.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 statsfe2.update.microsoft.com.akadns.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "statsfe2.update.microsoft.com.akadns.net," %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 statsfe2.update.microsoft.com.akadns.net,>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "statsfe2.ws.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 statsfe2.ws.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "survey.watson.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 survey.watson.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "survey.watson.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 survey.watson.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "view.atdmt.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 view.atdmt.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "vortex-bn2.metron.live.com.nsatc.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 vortex-bn2.metron.live.com.nsatc.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "vortex-cy2.metron.live.com.nsatc.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 vortex-cy2.metron.live.com.nsatc.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "watson.live.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 watson.live.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "watson.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 watson.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "watson.telemetry.microsoft.com.nsatc.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 watson.telemetry.microsoft.com.nsatc.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "wes.df.telemetry.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 wes.df.telemetry.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "win10.ipv6.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 win10.ipv6.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "www.bingads.microsoft.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 www.bingads.microsoft.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "www.go.microsoft.akadns.net" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 www.go.microsoft.akadns.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "www.msftncsi.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 www.msftncsi.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "a248.e.akamai.net" %WINDIR%\system32\drivers\etc\hosts
+rem skype & itunes issues
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 a248.e.akamai.net>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "apps.skype.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 apps.skype.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "c.msn.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 c.msn.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "pricelist.skype.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 pricelist.skype.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "s.gateway.messenger.live.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 s.gateway.messenger.live.com>>%WINDIR%\system32\drivers\etc\hosts
+find /C /I "ui.skype.com" %WINDIR%\system32\drivers\etc\hosts
+if %ERRORLEVEL% NEQ 0 echo ^0.0.0.0 ui.skype.com>>%WINDIR%\system32\drivers\etc\hosts
+attrib +r "%WINDIR%\system32\drivers\etc\hosts" > nul 2>&1
+
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+109
+echo Done %PRun% / %PMax% Blocking More Windows Servers. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+
+:7100
+echo.
+echo ###############################################################################
+echo # 2.7. Blocking More Windows Servers -- End #
+echo ###############################################################################
+echo.
+
+rem ========== 2.8. Disable Windows Error Recovery on Startup ==========
+
+echo.
+echo ###############################################################################
+echo # 2.8. Disable Windows Error Recovery on Startup -- Start #
+echo ###############################################################################
+echo.
+
+:8000
+set /A Pline=8000
+set PMax=1
+set PRun=0
+rem set PAct=0
+echo Disable Windows Error Recovery on Startup (2).
+set /p Pselect="Continue? y/n: "
+if '%Pselect%' == 'y' set /A Pline=%Pline%+1
+if '%Pselect%' == 'n' set /A Pline=%Pline%+100
+goto %Pline%
+
+:8001
+bcdedit /set recoveryenabled NO > nul 2>&1
+bcdedit /set {current} bootstatuspolicy ignoreallfailures > nul 2>&1
+
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+2
+echo Done %PRun% / %PMax% Disable Windows Error Recovery on Startup. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+
+:8100
+echo.
+echo ###############################################################################
+echo # 2.8. Disable Windows Error Recovery on Startup -- End #
+echo ###############################################################################
+echo.
+
+rem ========== 2.9. Internet Explorer 11 Tweaks ==========
+
+echo.
+echo ###############################################################################
+echo # 2.9. Internet Explorer 11 Tweaks -- Start #
+echo ###############################################################################
+echo.
+
+:9000
+set /A Pline=9000
+set PMax=3
+set PRun=0
+rem set PAct=0
+echo Internet Explorer 11 Tweaks.
+set /p Pselect="Continue? y/n: "
+if '%Pselect%' == 'y' set /A Pline=%Pline%+1
+if '%Pselect%' == 'n' set /A Pline=%Pline%+100
+goto %Pline%
+
+:9001
+set myMSG=Internet Explorer 11 Tweaks (Basic)(15).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:9002
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\Main" /v "DoNotTrack" /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\Main" /v "Search Page" /t REG_SZ /d "http://www.google.com" /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\Main" /v "Start Page Redirect Cache" /t REG_SZ /d "http://www.google.com" /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\Main" /v "DisableFirstRunCustomize" /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\Main" /v "RunOnceHasShown" /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\Main" /v "RunOnceComplete" /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKLM\SOFTWARE\Microsoft\Internet Explorer\Main" /v "DisableFirstRunCustomize" /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKLM\SOFTWARE\Microsoft\Internet Explorer\Main" /v "RunOnceHasShown" /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKLM\SOFTWARE\Microsoft\Internet Explorer\Main" /v "RunOnceComplete" /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKCU\Software\Policies\Microsoft\Internet Explorer\Main" /v "DisableFirstRunCustomize" /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKCU\Software\Policies\Microsoft\Internet Explorer\Main" /v "RunOnceHasShown" /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKCU\Software\Policies\Microsoft\Internet Explorer\Main" /v "RunOnceComplete" /t REG_DWORD /d 1 /f > nul 2>&1
+
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\Main" /v "PlaySounds" /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\Main" /v "Isolation" /t REG_SZ /d PMEM /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\Main" /v "Isolation64Bit" /t REG_DWORD /d 1 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+15
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:9003
+set myMSG=Disable IE Suggested Sites & Flip ahead (page prediction which sends browsing history to Microsoft).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:9004
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\Suggested Sites" /v "Enabled" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\Suggested Sites" /v "DataStreamEnabledState" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\FlipAhead" /v "FPEnabled" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+3
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:9005
+set myMSG=Add Google as search provider for IE11, and make it the default (11).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:9006
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\SearchScopes\{89418666-DF74-4CAC-A2BD-B69FB4A0228A}" /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\SearchScopes\{89418666-DF74-4CAC-A2BD-B69FB4A0228A}" /v "DisplayName" /t REG_SZ /d "Google" /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\SearchScopes\{89418666-DF74-4CAC-A2BD-B69FB4A0228A}" /v "FaviconURL" /t REG_SZ /d "http://www.google.com/favicon.ico" /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\SearchScopes\{89418666-DF74-4CAC-A2BD-B69FB4A0228A}" /v "FaviconURLFallback" /t REG_SZ /d "http://www.google.com/favicon.ico" /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\SearchScopes\{89418666-DF74-4CAC-A2BD-B69FB4A0228A}" /v "OSDFileURL" /t REG_SZ /d "http://www.iegallery.com/en-us/AddOns/DownloadAddOn?resourceId=813" /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\SearchScopes\{89418666-DF74-4CAC-A2BD-B69FB4A0228A}" /v "ShowSearchSuggestions" /t REG_DWORD /d 1 /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\SearchScopes\{89418666-DF74-4CAC-A2BD-B69FB4A0228A}" /v "SuggestionsURL" /t REG_SZ /d "http://clients5.google.com/complete/search?q={searchTerms}&client=ie8&mw={ie:maxWidth}&sh={ie:sectionHeight}&rh={ie:rowHeight}&inputencoding={inputEncoding}&outputencoding={outputEncoding}" /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\SearchScopes\{89418666-DF74-4CAC-A2BD-B69FB4A0228A}" /v "SuggestionsURLFallback" /t REG_SZ /d "http://clients5.google.com/complete/search?hl={language}&q={searchTerms}&client=ie8&inputencoding={inputEncoding}&outputencoding={outputEncoding}" /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\SearchScopes\{89418666-DF74-4CAC-A2BD-B69FB4A0228A}" /v "TopResultURLFallback" /t REG_SZ /d "" /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\SearchScopes\{89418666-DF74-4CAC-A2BD-B69FB4A0228A}" /v "URL" /t REG_SZ /d "http://www.google.com/search?q={searchTerms}&sourceid=ie7&rls=com.microsoft:{language}:{referrer:source}&ie={inputEncoding?}&oe={outputEncoding?}" /f > nul 2>&1
+reg add "HKCU\SOFTWARE\Microsoft\Internet Explorer\SearchScopes" /v "DefaultScope" /t REG_SZ /d "{89418666-DF74-4CAC-A2BD-B69FB4A0228A}" /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+11
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:9007
+:9008
+
+:9100
+echo.
+echo ###############################################################################
+echo # 2.9. Internet Explorer 11 Tweaks -- End #
+echo ###############################################################################
+echo.
+
+rem ========== 2.10. Libraries Tweaks ==========
+
+echo.
+echo ###############################################################################
+echo # 2.10. Libraries Tweaks -- Start #
+echo ###############################################################################
+echo.
+
+:10000
+set /A Pline=10000
+set PMax=8
+set PRun=0
+rem set PAct=0
+echo Libraries Tweaks.
+set /p Pselect="Continue? y/n: "
+if '%Pselect%' == 'y' set /A Pline=%Pline%+1
+if '%Pselect%' == 'n' set /A Pline=%Pline%+100
+goto %Pline%
+
+:10001
+set myMSG=Remove Music, Pictures & Videos from Start Menu places (Settings > Personalization > Start > Choose which folders appear on Start)(3).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:10002
+del "C:\ProgramData\Microsoft\Windows\Start Menu Places\05 - Music.lnk"
+del "C:\ProgramData\Microsoft\Windows\Start Menu Places\06 - Pictures.lnk"
+del "C:\ProgramData\Microsoft\Windows\Start Menu Places\07 - Videos.lnk"
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+3
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:10003
+set myMSG=Remove Music, Pictures & Videos from Libraries (3).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:10004
+del "%userprofile%\AppData\Roaming\Microsoft\Windows\Libraries\Music.library-ms"
+del "%userprofile%\AppData\Roaming\Microsoft\Windows\Libraries\Pictures.library-ms"
+del "%userprofile%\AppData\Roaming\Microsoft\Windows\Libraries\Videos.library-ms"
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+3
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:10005
+set myMSG=Remove Libraries (60).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:10006
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\UsersLibraries" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\{031E4825-7B94-4dc3-B131-E946B44C8DD5}" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{59BD6DD1-5CEC-4d7e-9AD2-ECC64154418D}" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{C4D98F09-6124-4fe0-9942-826416082DA9}" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\{031E4825-7B94-4dc3-B131-E946B44C8DD5}" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{59BD6DD1-5CEC-4d7e-9AD2-ECC64154418D}" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{C4D98F09-6124-4fe0-9942-826416082DA9}" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\UsersLibraries" /f
+reg delete "HKCU\SOFTWARE\Classes\Local Settings\MuiCache\1\52C64B7E" /v "@C:\Windows\system32\windows.storage.dll,-50691" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\SettingSync\WindowsSettingHandlers\UserLibraries" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\SettingSync\WindowsSettingHandlers\UserLibraries" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\SettingSync\WindowsSettingHandlers\UserLibraries" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\SettingSync\Namespace\Windows\UserLibraries" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\SettingSync\Namespace\Windows\UserLibraries" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\SettingSync\Namespace\Windows\UserLibraries" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.NavPaneShowLibraries" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.NavPaneShowLibraries" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.NavPaneShowLibraries" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SettingSync\Namespace\Windows\UserLibraries" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SettingSync\Namespace\Windows\UserLibraries" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SettingSync\Namespace\Windows\UserLibraries" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SettingSync\WindowsSettingHandlers\UserLibraries" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SettingSync\WindowsSettingHandlers\UserLibraries" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SettingSync\WindowsSettingHandlers\UserLibraries" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.NavPaneShowLibraries" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.NavPaneShowLibraries" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.NavPaneShowLibraries" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{c51b83e5-9edd-4250-b45a-da672ee3c70e}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{c51b83e5-9edd-4250-b45a-da672ee3c70e}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\CLSID\{c51b83e5-9edd-4250-b45a-da672ee3c70e}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{c51b83e5-9edd-4250-b45a-da672ee3c70e}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{c51b83e5-9edd-4250-b45a-da672ee3c70e}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{c51b83e5-9edd-4250-b45a-da672ee3c70e}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{e9711a2f-350f-4ec1-8ebd-21245a8b9376}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{e9711a2f-350f-4ec1-8ebd-21245a8b9376}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\CLSID\{e9711a2f-350f-4ec1-8ebd-21245a8b9376}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{1CF324EC-F905-4c69-851A-DDC8795F71F2}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{1CF324EC-F905-4c69-851A-DDC8795F71F2}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\CLSID\{1CF324EC-F905-4c69-851A-DDC8795F71F2}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{1CF324EC-F905-4c69-851A-DDC8795F71F2}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{1CF324EC-F905-4c69-851A-DDC8795F71F2}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{1CF324EC-F905-4c69-851A-DDC8795F71F2}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{51F649D3-4BFF-42f6-A253-6D878BE1651D}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{51F649D3-4BFF-42f6-A253-6D878BE1651D}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\CLSID\{51F649D3-4BFF-42f6-A253-6D878BE1651D}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{51F649D3-4BFF-42f6-A253-6D878BE1651D}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{51F649D3-4BFF-42f6-A253-6D878BE1651D}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{51F649D3-4BFF-42f6-A253-6D878BE1651D}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{896664F7-12E1-490f-8782-C0835AFD98FC}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{896664F7-12E1-490f-8782-C0835AFD98FC}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\CLSID\{896664F7-12E1-490f-8782-C0835AFD98FC}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{896664F7-12E1-490f-8782-C0835AFD98FC}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{896664F7-12E1-490f-8782-C0835AFD98FC}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{896664F7-12E1-490f-8782-C0835AFD98FC}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{031E4825-7B94-4dc3-B131-E946B44C8DD5}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{031E4825-7B94-4dc3-B131-E946B44C8DD5}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\CLSID\{031E4825-7B94-4dc3-B131-E946B44C8DD5}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{031E4825-7B94-4dc3-B131-E946B44C8DD5}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{031E4825-7B94-4dc3-B131-E946B44C8DD5}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{031E4825-7B94-4dc3-B131-E946B44C8DD5}" /f
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+60
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:10007
+set myMSG=Remove "Show Libraries" from Folder Options -> View tab (Advanced Settings).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:10008
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\NavPane\ShowLibraries" /f
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:10009
+set myMSG=Remove Music (appears under This PC in File Explorer)(28).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:10010
+reg delete "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "My Music" /f
+reg delete "HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "My Music" /f
+reg delete "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "My Music" /f
+reg delete "HKEY_CLASSES_ROOT\SystemFileAssociations\MyMusic" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "CommonMusic" /f
+reg delete "HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "My Music" /f
+reg delete "HKEY_USERS\S-1-5-19\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "My Music" /f
+reg delete "HKEY_USERS\S-1-5-20\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "My Music" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{1CF1260C-4DD0-4ebb-811F-33C572699FDE}" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{3dfdf296-dbec-4fb4-81d1-6a3438bcf4de}" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "CommonMusic" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "CommonMusic" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "CommonMusic" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{3dfdf296-dbec-4fb4-81d1-6a3438bcf4de}" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{1CF1260C-4DD0-4ebb-811F-33C572699FDE}" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{3f2a72a7-99fa-4ddb-a5a8-c604edf61d6b}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{1CF1260C-4DD0-4ebb-811F-33C572699FDE}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{1CF1260C-4DD0-4ebb-811F-33C572699FDE}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\CLSID\{1CF1260C-4DD0-4ebb-811F-33C572699FDE}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{3dfdf296-dbec-4fb4-81d1-6a3438bcf4de}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{3dfdf296-dbec-4fb4-81d1-6a3438bcf4de}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\CLSID\{3dfdf296-dbec-4fb4-81d1-6a3438bcf4de}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{1CF1260C-4DD0-4ebb-811F-33C572699FDE}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{1CF1260C-4DD0-4ebb-811F-33C572699FDE}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{1CF1260C-4DD0-4ebb-811F-33C572699FDE}" /f
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{3dfdf296-dbec-4fb4-81d1-6a3438bcf4de}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{3dfdf296-dbec-4fb4-81d1-6a3438bcf4de}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{3dfdf296-dbec-4fb4-81d1-6a3438bcf4de}" /f
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+28
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:10011
+set myMSG=Remove Pictures (appears under This PC in File Explorer) (41).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:10012
+reg delete "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "My Pictures" /f
+reg delete "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "My Pictures" /f
+reg delete "HKEY_CLASSES_ROOT\SystemFileAssociations\MyPictures" /f
+reg delete "HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "My Pictures" /f
+reg delete "HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "My Pictures" /f
+reg delete "HKEY_USERS\.DEFAULT\Software\Classes\Local Settings\MuiCache\1\52C64B7E" /v "@C:\Windows\System32\Windows.UI.Immersive.dll,-38304" /f
+reg delete "HKEY_USERS\S-1-5-19\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "My Pictures" /f
+reg delete "HKEY_USERS\S-1-5-20\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "My Pictures" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "CommonPictures" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{0b2baaeb-0042-4dca-aa4d-3ee8648d03e5}" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\StartMenu\StartPanel\PinnedItems\Pictures" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "CommonPictures" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{b3690e58-e961-423b-b687-386ebfd83239}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{b3690e58-e961-423b-b687-386ebfd83239}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{b3690e58-e961-423b-b687-386ebfd83239}" /f
+
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{c1f8339f-f312-4c97-b1c6-ecdf5910c5c0}" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{0b2baaeb-0042-4dca-aa4d-3ee8648d03e5}" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{4dcafe13-e6a7-4c28-be02-ca8c2126280d}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{b3690e58-e961-423b-b687-386ebfd83239}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{b3690e58-e961-423b-b687-386ebfd83239}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{b3690e58-e961-423b-b687-386ebfd83239}" /f
+
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{c1f8339f-f312-4c97-b1c6-ecdf5910c5c0}" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{24ad3ad4-a569-4530-98e1-ab02f9417aa8}" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "CommonPictures" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "CommonPictures" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{24ad3ad4-a569-4530-98e1-ab02f9417aa8}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Wow6432Node\Classes\CLSID\{3ADD1653-EB32-4cb0-BBD7-DFA0ABB5ACCA}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Wow6432Node\Classes\CLSID\{3ADD1653-EB32-4cb0-BBD7-DFA0ABB5ACCA}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKLM\SOFTWARE\Wow6432Node\Classes\CLSID\{3ADD1653-EB32-4cb0-BBD7-DFA0ABB5ACCA}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Wow6432Node\Classes\CLSID\{24ad3ad4-a569-4530-98e1-ab02f9417aa8}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Wow6432Node\Classes\CLSID\{24ad3ad4-a569-4530-98e1-ab02f9417aa8}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKLM\SOFTWARE\Wow6432Node\Classes\CLSID\{24ad3ad4-a569-4530-98e1-ab02f9417aa8}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{3ADD1653-EB32-4cb0-BBD7-DFA0ABB5ACCA}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{3ADD1653-EB32-4cb0-BBD7-DFA0ABB5ACCA}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\CLSID\{3ADD1653-EB32-4cb0-BBD7-DFA0ABB5ACCA}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{24ad3ad4-a569-4530-98e1-ab02f9417aa8}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{24ad3ad4-a569-4530-98e1-ab02f9417aa8}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\CLSID\{24ad3ad4-a569-4530-98e1-ab02f9417aa8}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{3ADD1653-EB32-4cb0-BBD7-DFA0ABB5ACCA}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{3ADD1653-EB32-4cb0-BBD7-DFA0ABB5ACCA}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{3ADD1653-EB32-4cb0-BBD7-DFA0ABB5ACCA}" /f
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+41
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:10013
+set myMSG=Remove Videos (appears under This PC in File Explorer) (29).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:10014
+reg delete "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "My Video" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "CommonVideo" /f
+reg delete "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "My Video" /f
+reg delete "HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "My Video" /f
+reg delete "HKEY_CLASSES_ROOT\SystemFileAssociations\MyVideo" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "CommonVideo" /f
+reg delete "HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "My Video" /f
+reg delete "HKEY_USERS\S-1-5-19\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "My Video" /f
+reg delete "HKEY_USERS\S-1-5-20\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "My Video" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{f86fa3ab-70d2-4fc7-9c99-fcbf05467f3a}" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "CommonVideo" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{51294DA1-D7B1-485b-9E9A-17CFFE33E187}" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{ea25fbd7-3bf7-409e-b97f-3352240903f4}" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{292108be-88ab-4f33-9a26-7748e62e37ad}" /f
+reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{5fa96407-7e77-483c-ac93-691d05850de8}" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "CommonVideo" /f
+reg delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\FolderTypes\{51294DA1-D7B1-485b-9E9A-17CFFE33E187}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{f86fa3ab-70d2-4fc7-9c99-fcbf05467f3a}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{f86fa3ab-70d2-4fc7-9c99-fcbf05467f3a}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\CLSID\{f86fa3ab-70d2-4fc7-9c99-fcbf05467f3a}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{A0953C92-50DC-43bf-BE83-3742FED03C9C}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\CLSID\{A0953C92-50DC-43bf-BE83-3742FED03C9C}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\CLSID\{A0953C92-50DC-43bf-BE83-3742FED03C9C}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{f86fa3ab-70d2-4fc7-9c99-fcbf05467f3a}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{f86fa3ab-70d2-4fc7-9c99-fcbf05467f3a}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{f86fa3ab-70d2-4fc7-9c99-fcbf05467f3a}" /f
+
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{A0953C92-50DC-43bf-BE83-3742FED03C9C}" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem %SystemRoot%\System32\setaclx64 -on "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{A0953C92-50DC-43bf-BE83-3742FED03C9C}" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg delete "HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{A0953C92-50DC-43bf-BE83-3742FED03C9C}" /f
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+29
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:10015
+set myMSG=Remove Pictures, Music, Videos from MUIcache (5).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:10016
+reg delete "HKCU\SOFTWARE\Classes\Local Settings\MuiCache\1\52C64B7E" /v "@windows.storage.dll,-21790" /f
+reg delete "HKCU\SOFTWARE\Classes\Local Settings\MuiCache\1\52C64B7E" /v "@windows.storage.dll,-34584" /f
+reg delete "HKCU\SOFTWARE\Classes\Local Settings\MuiCache\1\52C64B7E" /v "@windows.storage.dll,-34595" /f
+reg delete "HKCU\SOFTWARE\Classes\Local Settings\MuiCache\1\52C64B7E" /v "@windows.storage.dll,-34620" /f
+reg delete "HKEY_USERS\.DEFAULT\Software\Classes\Local Settings\MuiCache\1\52C64B7E" /v "@windows.storage.dll,-21790" /f
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+5
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:10017
+:10018
+
+:10100
+echo.
+echo ###############################################################################
+echo # 2.10. Libraries Tweaks -- End #
+echo ###############################################################################
+echo.
+
+
+rem ========== 2.11. Windows Update Tweaks ==========
+
+echo.
+echo ###############################################################################
+echo # 2.11. Windows Update Tweaks -- Start #
+echo ###############################################################################
+echo.
+
+:11000
+set /A Pline=11000
+set PMax=4
+set PRun=0
+rem set PAct=0
+echo Windows Update Tweaks.
+set /p Pselect="Continue? y/n: "
+if '%Pselect%' == 'y' set /A Pline=%Pline%+1
+if '%Pselect%' == 'n' set /A Pline=%Pline%+100
+goto %Pline%
+
+:11001
+set myMSG=Windows Update - Notify first.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:11002
+net stop wuauserv > nul 2>&1
+reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" /v "AutoInstallMinorUpdates" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" /v AUOptions /t REG_DWORD /d 2 /f > nul 2>&1
+reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" /v NoAutoUpdate /t REG_DWORD /d 0 /f > nul 2>&1
+net start wuauserv > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+5
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:11003
+set myMSG=Change how Windows Updates are delivered - allow only directly from Microsoft.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:11004
+rem 0 = Off (only directly from Microsoft)
+rem 1 = Get updates from Microsoft and PCs on your local network
+rem 3 = Get updates from Microsoft, PCs on your local network & PCs on the Internet (like how torrents work)
+reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config" /v "DODownloadMode" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:11005
+set myMSG=Disable Windows Update sharing (2).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:11006
+reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config" /v "DownloadMode" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config" /v "DODownloadMode" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+2
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:11007
+set myMSG=Disable automatic Windows Updates.
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:11008
+reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v "AUOptions" /t REG_DWORD /d 2 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+1
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:11009
+:11010
+
+:11100
+echo.
+echo ###############################################################################
+echo # 2.11. Windows Update Tweaks -- End #
+echo ###############################################################################
+echo.
+
+
+rem ========== 2.12. Windows Defender Tweaks ==========
+
+echo.
+echo ###############################################################################
+echo # 2.12. Windows Defender Tweaks -- Start #
+echo ###############################################################################
+echo.
+
+:12000
+set /A Pline=12000
+set PMax=2
+set PRun=0
+rem set PAct=0
+echo Windows Defender Tweaks.
+set /p Pselect="Continue? y/n: "
+if '%Pselect%' == 'y' set /A Pline=%Pline%+1
+if '%Pselect%' == 'n' set /A Pline=%Pline%+100
+goto %Pline%
+
+:12001
+set myMSG=Don't allow Windows Defender to submit samples to MAPS (formerly SpyNet) (4).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:12002
+rem ext
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Microsoft\Windows Defender\Spynet" -ot reg -actn setowner -ownr "n:Administrators" -rec yes
+rem %SystemRoot%\System32\setaclx64 -on "HKLM\SOFTWARE\Microsoft\Windows Defender\Spynet" -ot reg -actn ace -ace "n:Administrators;p:full" -rec yes
+reg add "HKLM\SOFTWARE\Microsoft\Windows Defender\Spynet" /v "SpyNetReporting" /t REG_DWORD /d 0 /f > nul 2>&1
+reg add "HKLM\SOFTWARE\Microsoft\Windows Defender\Spynet" /v "SubmitSamplesConsent" /t REG_DWORD /d 0 /f > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+4
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:12003
+set myMSG=Disable Windows Defender (8).
+echo %myMSG%
+set /p regTweak="Continue? y/n: "
+if '%regTweak%' == 'y' set /A Pline=%Pline%+1
+if '%regTweak%' == 'n' set /A Pline=%Pline%+2
+goto %Pline%
+:12004
+sc config WinDefend start= Disabled > nul 2>&1
+sc config WdNisSvc start= Disabled > nul 2>&1
+reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows Defender" /v "DisableAntiSpyware" /t REG_DWORD /d 1 /f > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\Windows Defender\Windows Defender Cache Maintenance" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\Windows Defender\Windows Defender Cleanup" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\Windows Defender\Windows Defender Scheduled Scan" /Disable > nul 2>&1
+schtasks /Change /TN "Microsoft\Windows\Windows Defender\Windows Defender Verification" /Disable > nul 2>&1
+del "C:\ProgramData\Microsoft\Windows Defender\Scans\mpcache*" /s > nul 2>&1
+set /A PRun=%PRun%+1
+set /A PAct=%PAct%+4
+echo Done %PRun% / %PMax%. Total Actions %PAct%.
+timeout /T 1 /NOBREAK > nul
+set /A Pline=%Pline%+1
+if '%Pselect%' == 'a' set /A Pline=%Pline%+1
+goto %Pline%
+
+:12005
+:12006
+
+:12100
+echo.
+echo ###############################################################################
+echo # 2.12. Windows Defender Tweaks -- End #
+echo ###############################################################################
+echo.
+
+rem ========== Finish ==========
+
+:finish
+echo.
+echo ###############################################################################
+echo # #
+echo # Windows10MiningTweaksDmW Version %V% #
+echo # #
+echo # AUTHOR: DeadManWalking (DeadManWalkingTO-GitHub) #
+echo # #
+echo ###############################################################################
+echo # Total Actions %PAct%.
+echo ###############################################################################
+echo # #
+echo # Finish. Ready for mining! #
+echo # #
+echo # Press any key to exit. #
+echo # #
+echo ###############################################################################
+
+pause > nul
+
+rem ========== End ==========
+
+rem ========== EoF ==========
diff --git a/Utils/prerun/AMDPrerun.bat b/Utils/prerun/AMDPrerun.bat
new file mode 100644
index 0000000000..8ff7942134
--- /dev/null
+++ b/Utils/prerun/AMDPrerun.bat
@@ -0,0 +1,7 @@
+REM This file will run any time an AMD miner is launched if it exists
+
+setx GPU_FORCE_64BIT_PTR 0
+setx GPU_MAX_HEAP_SIZE 100
+setx GPU_USE_SYNC_OBJECTS 1
+setx GPU_MAX_ALLOC_PERCENT 100
+setx GPU_SINGLE_ALLOC_PERCENT 100
diff --git a/Utils/prerun/Comannd Line.txt b/Utils/prerun/Comannd Line.txt
new file mode 100644
index 0000000000..65cb543501
--- /dev/null
+++ b/Utils/prerun/Comannd Line.txt
@@ -0,0 +1,70 @@
+Command Line:
+-p[gpu_id]"Name"
+apply profile "Name" to GPU with id=[gpu_id]
+-c[gpu_id]"Name"
+same as above, but with confirmation message that application started and everything went ok.
+-r[gpu_id]
+reset GPU with id=[gpu_id]
+cp[gpu_id]"Name"
+compare current values of GPU with id=[gpu_id] with profile "Name", and eventually set this profile if not equal
+cm[gpu_id]"Name"
+compare current values of GPU with id=[gpu_id] with profile "Name", and eventually set this profile if not equal, with additional message if not equal found
+co[gpu_id]"Name"
+only compare current values of GPU with id=[gpu_id] with profile "Name", with message if not equal found
+-consoleonly
+displays all messages (eg. errors) in cmd.exe console window, instead of gui messages. Only commands that are put after -consoleonly are affected, example:
+"OverdriveNTool.exe" -consoleonly -r0 -p0"1" -r1 -p1"1" -r2 -p2"2" - will affect all commands
+"OverdriveNTool.exe" -r0 -p0"1" -r1 -consoleonly -p1"1" -r2 -p2"2" - will affect -p1"1" -r2 -p2"2" commands only
+-showgui
+when added to commandline normal GUI will be displayed after program finishes with all other commands
+-wait[miliseconds]
+program waits specified time before parsing next command, useful if you want to add some delay for example on windows startup, can be used multiple times in one commandline
+example: OverdriveNTool.exe -wait3000 -r0 -wait500 -p0profile1
+
+[gpu_id] - it's the first number taken from GPU description, for single video card it's 0
+"Name" - name of the profile that was saved ealier, must be quoted if has spaces inside
+
+example:
+OverdriveNTool.exe -p0myProfile -p1"Profile 2"
+In this example application starts without gui, then sets "myProfile" to GPU with id=0 and "Profile 2" to GPU with id=1 and then exit.
+
+commands can be used all together, for example:
+OverdriveNTool.exe -p0myProfile -r0 co1"Profile 1"
+On configs with more than 10 GPUs [gpu_id] must have 2 digits, for GPUs 0-9 leading 0 must be added, example: 00,01,02,03,04,05,06,07,08,09,10,11,12. Usage example: -p05"Name"
+It's possible to use * as [gpu_id], which means it affects all supported GPUs, example:
+-r* -p*MyProfile -p2"Custom profile" cm*MyProfile
+
+Advanced:
+-ac[gpu_id] GPU_P[num]=[value];[value][;0] Mem_P[num]=[value];[value][;0] Fan_Min=[value] Fan_Max=[value] Fan_Target=[value] Fan_Acoustic=[value] Power_Temp=[value] Power_Target=[value]
+-ac is similar to -p command, applies values but without using profiles. Format is identical to ini profile. All not specified values will remain untouched. Can be used with other commands (-consoleonly, * as [gpu_id], -r, -p... etc.)
+[num] - Pstate number, using # as [num] will apply to highest available Pstate for scpecified GPU
+[value] – value, for GPU and memory PState first value is clock (MHz), second is voltage (mV), third optional ;0 makes this Pstate disabled.
+Putting * as Memory or GPU value will skip applying this value, for example:
+-ac0 GPU_P7=*;800 Mem_P3=1000;* (only applies GPU_P7 voltage=800mV and Memory P3 clock=1000MHZ)
+-ac0 GPU_P4=*;*;0 (only disables GPU_P4 without changing it’s values)
+
+For I2C settings use –ac with Offset=[value] LLC=[value] PhaseGain=[value] CurrentScale=[value]
+I2C must be enabled and supported for specified GPU, otherwise it will not work. Offset value is multiplied by 6,25mV, so 10 = +62,5mV, -5 = -31,25mV
+Example:
+-ac0 Offset=10 LLC=0
+-ac0 Offset=-5 LLC=1 PhaseGain=000000 CurrentScale=60
+
+Commands example:
+-ac0 GPU_P7=1200;800 Mem_P2=1000;850 Fan_Min=1080 Fan_Max=1700 Fan_Target=70 Fan_Acoustic=700 Power_Temp=90 Power_Target=50 -ac1 GPU_P#=1200;800 Mem_P#=1000;850
+-ac0 GPU_P7=1200;800;0 Mem_P3=1000;850 Fan_Min=1080 Fan_Max=1700
+-consoleonly -r5 -ac5 GPU_P#=1200;800 Mem_P#=1000;850 Fan_Min=1080 Fan_Max=1700 -ac4 Fan_Target=70 Fan_Acoustic=700 Power_Temp=90 Power_Target=50
+-ac* Power_Target=-1 GPU_P7=*;*;0
+-wait1000 -r0 -ac0 GPU_P7=1200;800 Mem_P1=700;850;0 Mem_P2=750;850;0 Mem_P3=800;850;0 Mem_P4=1000;850 Fan_Min=1080 Fan_Max=1700 Fan_Target=70 Fan_Acoustic=700 Power_Temp=90 Power_Target=50
+-ac0 Power_Target=50 -ac1 Power_Target=-50 -ac2 Fan_Max=1700 Fan_Min=1080 -ac1 Fan_Acoustic=700
+
+-getcurrent - prints current values for all supported GPUs in cmd console window.
+-t[gpu_id]
+restart GPU with id=[gpu_id]. It's similar to devices manager enable/disable GPU. Useful for immediately apply registry changes done to AMD keys like SoftPowerPlay table. It requires admin rigths to work.
+
+Additional info:
+-Workaround for bug in 17.7.2 drivers, when driver sometimes uses default voltages instead of user settings: use reset and re-apply profile.
+-It's possible to disable/enable each P state. To do this click on P0, P1.. etc. label. If P state is disabled it will not be used by GPU.
+-I2C currently supports: IR3567B (RX470, RX480, some RX5xx), up9505 (MSI RX5xx)
+-If you prefer to not touch fan settings it's possible to deactivate Fan section for each GPU. To do this press Ctrl + double click somewhere on the Fan box. It's saved per gpu_id, so GUI or commandline will not touch fan settings for such GPU.
+-To open Settings or SoftPowerPlayTable editor left click on top-left program icon, or right click on the titlebar.
+-To change "friendly name" first enable it in settings, than right click on the gpu list to open menu
diff --git a/Utils/prerun/OverdriveNTool.exe b/Utils/prerun/OverdriveNTool.exe
new file mode 100644
index 0000000000..9bbf93d6f9
Binary files /dev/null and b/Utils/prerun/OverdriveNTool.exe differ
diff --git a/Utils/prerun/OverdriveNTool.ini b/Utils/prerun/OverdriveNTool.ini
new file mode 100644
index 0000000000..a30150b485
Binary files /dev/null and b/Utils/prerun/OverdriveNTool.ini differ
diff --git a/Utils/prerun/blake2b-example.bat b/Utils/prerun/blake2b-example.bat
new file mode 100644
index 0000000000..7a96589410
--- /dev/null
+++ b/Utils/prerun/blake2b-example.bat
@@ -0,0 +1,17 @@
+REM This file will run for blake2b algo
+REM This file and nvidia inspector is disabled by default to Enable them, rename this file from blake2b-example.bat to blake2b.bat
+REM Below is a example for a 6 GPU setup
+
+SET PL=61
+SET MEMORY=-650
+SET CORE=25
+SET TEMP=90
+
+SET GPU0=-setBaseClockOffset:0,0,%CORE% -setMemoryClockOffset:0,0,%MEMORY% -setPowerTarget:0,%PL% -setTempTarget:0,0,%TEMP%
+SET GPU1=-setBaseClockOffset:1,0,%CORE% -setMemoryClockOffset:1,0,%MEMORY% -setPowerTarget:1,%PL% -setTempTarget:1,0,%TEMP%
+SET GPU2=-setBaseClockOffset:2,0,%CORE% -setMemoryClockOffset:2,0,%MEMORY% -setPowerTarget:2,%PL% -setTempTarget:2,0,%TEMP%
+SET GPU3=-setBaseClockOffset:3,0,%CORE% -setMemoryClockOffset:3,0,%MEMORY% -setPowerTarget:3,%PL% -setTempTarget:3,0,%TEMP%
+SET GPU4=-setBaseClockOffset:4,0,%CORE% -setMemoryClockOffset:4,0,%MEMORY% -setPowerTarget:4,%PL% -setTempTarget:4,0,%TEMP%
+SET GPU5=-setBaseClockOffset:5,0,%CORE% -setMemoryClockOffset:5,0,%MEMORY% -setPowerTarget:5,%PL% -setTempTarget:5,0,%TEMP%
+
+nvidiaInspector.exe %GPU0% %GPU1% %GPU2% %GPU3% %GPU4% %GPU5%
diff --git a/Utils/prerun/bmw512-example.bat b/Utils/prerun/bmw512-example.bat
new file mode 100644
index 0000000000..7ea4a763e6
--- /dev/null
+++ b/Utils/prerun/bmw512-example.bat
@@ -0,0 +1,17 @@
+REM This file will run for bmw512 algo
+REM This file and nvidia inspector is disabled by default to Enable them, rename this file from bmw512-example.bat to bmw512.bat
+REM Below is a example for a 6 GPU setup
+
+SET PL=61
+SET MEMORY=-650
+SET CORE=25
+SET TEMP=90
+
+SET GPU0=-setBaseClockOffset:0,0,%CORE% -setMemoryClockOffset:0,0,%MEMORY% -setPowerTarget:0,%PL% -setTempTarget:0,0,%TEMP%
+SET GPU1=-setBaseClockOffset:1,0,%CORE% -setMemoryClockOffset:1,0,%MEMORY% -setPowerTarget:1,%PL% -setTempTarget:1,0,%TEMP%
+SET GPU2=-setBaseClockOffset:2,0,%CORE% -setMemoryClockOffset:2,0,%MEMORY% -setPowerTarget:2,%PL% -setTempTarget:2,0,%TEMP%
+SET GPU3=-setBaseClockOffset:3,0,%CORE% -setMemoryClockOffset:3,0,%MEMORY% -setPowerTarget:3,%PL% -setTempTarget:3,0,%TEMP%
+SET GPU4=-setBaseClockOffset:4,0,%CORE% -setMemoryClockOffset:4,0,%MEMORY% -setPowerTarget:4,%PL% -setTempTarget:4,0,%TEMP%
+SET GPU5=-setBaseClockOffset:5,0,%CORE% -setMemoryClockOffset:5,0,%MEMORY% -setPowerTarget:5,%PL% -setTempTarget:5,0,%TEMP%
+
+nvidiaInspector.exe %GPU0% %GPU1% %GPU2% %GPU3% %GPU4% %GPU5%
diff --git a/prerun/change.log b/Utils/prerun/change.log
similarity index 95%
rename from prerun/change.log
rename to Utils/prerun/change.log
index 0a909fbdd3..e33ca25fce 100644
--- a/prerun/change.log
+++ b/Utils/prerun/change.log
@@ -2,6 +2,14 @@
### NVIDIA INSPECTOR - CHANGELOG ###
###############################################
+NVIDIA Inspector - Version 1.9.8.1 Beta (.NET Framework 2 or above)
+
+- added support for HBM1, HBM2, SDDR4, GDDR6, GDDR6X memory
+- added DCH detection
+- added foundry info to GPU
+- fixed some crashes
+
+
NVIDIA Inspector - Version 1.9.7.8 (.NET Framework 2 or above)
- added "dpiAware" flag to support win8+ dpi scaling
diff --git a/Utils/prerun/cryptonightgpu-example.bat b/Utils/prerun/cryptonightgpu-example.bat
new file mode 100644
index 0000000000..5c670d7f9b
--- /dev/null
+++ b/Utils/prerun/cryptonightgpu-example.bat
@@ -0,0 +1,17 @@
+REM This file will run for cryptonightgpu algo
+REM This file and nvidia inspector is disabled by default to Enable them, rename this file from cryptonightgpu-example.bat to cryptonightgpu.bat
+REM Below is a example for a 6 GPU setup
+
+SET PL=61
+SET MEMORY=-650
+SET CORE=25
+SET TEMP=90
+
+SET GPU0=-setBaseClockOffset:0,0,%CORE% -setMemoryClockOffset:0,0,%MEMORY% -setPowerTarget:0,%PL% -setTempTarget:0,0,%TEMP%
+SET GPU1=-setBaseClockOffset:1,0,%CORE% -setMemoryClockOffset:1,0,%MEMORY% -setPowerTarget:1,%PL% -setTempTarget:1,0,%TEMP%
+SET GPU2=-setBaseClockOffset:2,0,%CORE% -setMemoryClockOffset:2,0,%MEMORY% -setPowerTarget:2,%PL% -setTempTarget:2,0,%TEMP%
+SET GPU3=-setBaseClockOffset:3,0,%CORE% -setMemoryClockOffset:3,0,%MEMORY% -setPowerTarget:3,%PL% -setTempTarget:3,0,%TEMP%
+SET GPU4=-setBaseClockOffset:4,0,%CORE% -setMemoryClockOffset:4,0,%MEMORY% -setPowerTarget:4,%PL% -setTempTarget:4,0,%TEMP%
+SET GPU5=-setBaseClockOffset:5,0,%CORE% -setMemoryClockOffset:5,0,%MEMORY% -setPowerTarget:5,%PL% -setTempTarget:5,0,%TEMP%
+
+nvidiaInspector.exe %GPU0% %GPU1% %GPU2% %GPU3% %GPU4% %GPU5%
diff --git a/Utils/prerun/default-example6gpu.bat b/Utils/prerun/default-example6gpu.bat
new file mode 100644
index 0000000000..defe9ba2d1
--- /dev/null
+++ b/Utils/prerun/default-example6gpu.bat
@@ -0,0 +1,17 @@
+REM This file will run for any algo if AlgoName.bat does not exist
+REM This file and nvidia inspector is disabled by default to Enable them, rename this file from default-example.bat to default.bat
+REM Below is a example for a 6 GPU setup
+
+SET PL=61
+SET MEMORY=225
+SET CORE=25
+SET TEMP=90
+
+SET GPU0=-setBaseClockOffset:0,0,%CORE% -setMemoryClockOffset:0,0,%MEMORY% -setPowerTarget:0,%PL% -setTempTarget:0,0,%TEMP%
+SET GPU1=-setBaseClockOffset:1,0,%CORE% -setMemoryClockOffset:1,0,%MEMORY% -setPowerTarget:1,%PL% -setTempTarget:1,0,%TEMP%
+SET GPU2=-setBaseClockOffset:2,0,%CORE% -setMemoryClockOffset:2,0,%MEMORY% -setPowerTarget:2,%PL% -setTempTarget:2,0,%TEMP%
+SET GPU3=-setBaseClockOffset:3,0,%CORE% -setMemoryClockOffset:3,0,%MEMORY% -setPowerTarget:3,%PL% -setTempTarget:3,0,%TEMP%
+SET GPU4=-setBaseClockOffset:4,0,%CORE% -setMemoryClockOffset:4,0,%MEMORY% -setPowerTarget:4,%PL% -setTempTarget:4,0,%TEMP%
+SET GPU5=-setBaseClockOffset:5,0,%CORE% -setMemoryClockOffset:5,0,%MEMORY% -setPowerTarget:5,%PL% -setTempTarget:5,0,%TEMP%
+
+nvidiaInspector.exe %GPU0% %GPU1% %GPU2% %GPU3% %GPU4% %GPU5%
diff --git a/Utils/prerun/default-example9gpu.bat b/Utils/prerun/default-example9gpu.bat
new file mode 100644
index 0000000000..777ead0ff4
--- /dev/null
+++ b/Utils/prerun/default-example9gpu.bat
@@ -0,0 +1,20 @@
+REM This file will run for any algo if AlgoName.bat does not exist
+REM This file and nvidia inspector is disabled by default to Enable them, rename this file from default-example.bat to default.bat
+REM Below is a example for a 6 GPU setup
+
+SET PL=61
+SET MEMORY=225
+SET CORE=25
+SET TEMP=90
+
+SET GPU0=-setBaseClockOffset:0,0,%CORE% -setMemoryClockOffset:0,0,%MEMORY% -setPowerTarget:0,%PL% -setTempTarget:0,0,%TEMP%
+SET GPU1=-setBaseClockOffset:1,0,%CORE% -setMemoryClockOffset:1,0,%MEMORY% -setPowerTarget:1,%PL% -setTempTarget:1,0,%TEMP%
+SET GPU2=-setBaseClockOffset:2,0,%CORE% -setMemoryClockOffset:2,0,%MEMORY% -setPowerTarget:2,%PL% -setTempTarget:2,0,%TEMP%
+SET GPU3=-setBaseClockOffset:3,0,%CORE% -setMemoryClockOffset:3,0,%MEMORY% -setPowerTarget:3,%PL% -setTempTarget:3,0,%TEMP%
+SET GPU4=-setBaseClockOffset:4,0,%CORE% -setMemoryClockOffset:4,0,%MEMORY% -setPowerTarget:4,%PL% -setTempTarget:4,0,%TEMP%
+SET GPU5=-setBaseClockOffset:5,0,%CORE% -setMemoryClockOffset:5,0,%MEMORY% -setPowerTarget:5,%PL% -setTempTarget:5,0,%TEMP%
+SET GPU6=-setBaseClockOffset:6,0,%CORE% -setMemoryClockOffset:6,0,%MEMORY% -setPowerTarget:6,%PL% -setTempTarget:6,0,%TEMP%
+SET GPU7=-setBaseClockOffset:7,0,%CORE% -setMemoryClockOffset:7,0,%MEMORY% -setPowerTarget:7,%PL% -setTempTarget:7,0,%TEMP%
+SET GPU8=-setBaseClockOffset:8,0,%CORE% -setMemoryClockOffset:8,0,%MEMORY% -setPowerTarget:8,%PL% -setTempTarget:8,0,%TEMP%
+
+nvidiaInspector.exe %GPU0% %GPU1% %GPU2% %GPU3% %GPU4% %GPU5% %GPU6% %GPU7% %GPU8%
diff --git a/Utils/prerun/ethash-example.bat b/Utils/prerun/ethash-example.bat
new file mode 100644
index 0000000000..722a3b0ea7
--- /dev/null
+++ b/Utils/prerun/ethash-example.bat
@@ -0,0 +1,17 @@
+REM This file will run for ethash algo
+REM This file and nvidia inspector is disabled by default to Enable them, rename this file from ethash-example.bat to ethash.bat
+REM Below is a example for a 6 GPU setup
+
+SET PL=61
+SET MEMORY=650
+SET CORE=25
+SET TEMP=90
+
+SET GPU0=-setBaseClockOffset:0,0,%CORE% -setMemoryClockOffset:0,0,%MEMORY% -setPowerTarget:0,%PL% -setTempTarget:0,0,%TEMP%
+SET GPU1=-setBaseClockOffset:1,0,%CORE% -setMemoryClockOffset:1,0,%MEMORY% -setPowerTarget:1,%PL% -setTempTarget:1,0,%TEMP%
+SET GPU2=-setBaseClockOffset:2,0,%CORE% -setMemoryClockOffset:2,0,%MEMORY% -setPowerTarget:2,%PL% -setTempTarget:2,0,%TEMP%
+SET GPU3=-setBaseClockOffset:3,0,%CORE% -setMemoryClockOffset:3,0,%MEMORY% -setPowerTarget:3,%PL% -setTempTarget:3,0,%TEMP%
+SET GPU4=-setBaseClockOffset:4,0,%CORE% -setMemoryClockOffset:4,0,%MEMORY% -setPowerTarget:4,%PL% -setTempTarget:4,0,%TEMP%
+SET GPU5=-setBaseClockOffset:5,0,%CORE% -setMemoryClockOffset:5,0,%MEMORY% -setPowerTarget:5,%PL% -setTempTarget:5,0,%TEMP%
+
+nvidiaInspector.exe %GPU0% %GPU1% %GPU2% %GPU3% %GPU4% %GPU5%
diff --git a/Utils/prerun/ethash-exampleamd.bat b/Utils/prerun/ethash-exampleamd.bat
new file mode 100644
index 0000000000..a178e653a8
--- /dev/null
+++ b/Utils/prerun/ethash-exampleamd.bat
@@ -0,0 +1 @@
+OverdriveNTool.exe -r0 -r1 -r2 -r3 -r4 -r5 -r6 -p0oc1 -p1oc1 -p2oc1 -p3oc1 -p4oc1 -p5oc1 -p6oc1
\ No newline at end of file
diff --git a/Utils/prerun/lyra2z330-example.bat b/Utils/prerun/lyra2z330-example.bat
new file mode 100644
index 0000000000..273c16509c
--- /dev/null
+++ b/Utils/prerun/lyra2z330-example.bat
@@ -0,0 +1,17 @@
+REM This file will run for lyra2z330 algo
+REM This file and nvidia inspector is disabled by default to Enable them, rename this file from lyra2z330-example.bat to lyra2z330.bat
+REM Below is a example for a 6 GPU setup
+
+SET PL=61
+SET MEMORY=650
+SET CORE=25
+SET TEMP=90
+
+SET GPU0=-setBaseClockOffset:0,0,%CORE% -setMemoryClockOffset:0,0,%MEMORY% -setPowerTarget:0,%PL% -setTempTarget:0,0,%TEMP%
+SET GPU1=-setBaseClockOffset:1,0,%CORE% -setMemoryClockOffset:1,0,%MEMORY% -setPowerTarget:1,%PL% -setTempTarget:1,0,%TEMP%
+SET GPU2=-setBaseClockOffset:2,0,%CORE% -setMemoryClockOffset:2,0,%MEMORY% -setPowerTarget:2,%PL% -setTempTarget:2,0,%TEMP%
+SET GPU3=-setBaseClockOffset:3,0,%CORE% -setMemoryClockOffset:3,0,%MEMORY% -setPowerTarget:3,%PL% -setTempTarget:3,0,%TEMP%
+SET GPU4=-setBaseClockOffset:4,0,%CORE% -setMemoryClockOffset:4,0,%MEMORY% -setPowerTarget:4,%PL% -setTempTarget:4,0,%TEMP%
+SET GPU5=-setBaseClockOffset:5,0,%CORE% -setMemoryClockOffset:5,0,%MEMORY% -setPowerTarget:5,%PL% -setTempTarget:5,0,%TEMP%
+
+nvidiaInspector.exe %GPU0% %GPU1% %GPU2% %GPU3% %GPU4% %GPU5%
diff --git a/Utils/prerun/neoscrypt-example.bat b/Utils/prerun/neoscrypt-example.bat
new file mode 100644
index 0000000000..1affb674ee
--- /dev/null
+++ b/Utils/prerun/neoscrypt-example.bat
@@ -0,0 +1,17 @@
+REM This file will run for neoscrypt algo
+REM This file and nvidia inspector is disabled by default to Enable them, rename this file from neoscrpyt-example.bat to neoscrypt.bat
+REM Below is a example for a 6 GPU setup
+
+SET PL=61
+SET MEMORY=-500
+SET CORE=25
+SET TEMP=90
+
+SET GPU0=-setBaseClockOffset:0,0,%CORE% -setMemoryClockOffset:0,0,%MEMORY% -setPowerTarget:0,%PL% -setTempTarget:0,0,%TEMP%
+SET GPU1=-setBaseClockOffset:1,0,%CORE% -setMemoryClockOffset:1,0,%MEMORY% -setPowerTarget:1,%PL% -setTempTarget:1,0,%TEMP%
+SET GPU2=-setBaseClockOffset:2,0,%CORE% -setMemoryClockOffset:2,0,%MEMORY% -setPowerTarget:2,%PL% -setTempTarget:2,0,%TEMP%
+SET GPU3=-setBaseClockOffset:3,0,%CORE% -setMemoryClockOffset:3,0,%MEMORY% -setPowerTarget:3,%PL% -setTempTarget:3,0,%TEMP%
+SET GPU4=-setBaseClockOffset:4,0,%CORE% -setMemoryClockOffset:4,0,%MEMORY% -setPowerTarget:4,%PL% -setTempTarget:4,0,%TEMP%
+SET GPU5=-setBaseClockOffset:5,0,%CORE% -setMemoryClockOffset:5,0,%MEMORY% -setPowerTarget:5,%PL% -setTempTarget:5,0,%TEMP%
+
+nvidiaInspector.exe %GPU0% %GPU1% %GPU2% %GPU3% %GPU4% %GPU5%
diff --git a/Utils/prerun/nvidiaInspector.exe b/Utils/prerun/nvidiaInspector.exe
new file mode 100644
index 0000000000..0669348697
Binary files /dev/null and b/Utils/prerun/nvidiaInspector.exe differ
diff --git a/prerun/nvidiaInspector.exe.config b/Utils/prerun/nvidiaInspector.exe.config
similarity index 100%
rename from prerun/nvidiaInspector.exe.config
rename to Utils/prerun/nvidiaInspector.exe.config
diff --git a/Utils/prerun/nvidiaInspector.ver b/Utils/prerun/nvidiaInspector.ver
new file mode 100644
index 0000000000..5d663e4212
--- /dev/null
+++ b/Utils/prerun/nvidiaInspector.ver
@@ -0,0 +1 @@
+1.9.8.1
\ No newline at end of file
diff --git a/Utils/prerun/nvidiaProfileInspector.exe b/Utils/prerun/nvidiaProfileInspector.exe
new file mode 100644
index 0000000000..25fd82644c
Binary files /dev/null and b/Utils/prerun/nvidiaProfileInspector.exe differ
diff --git a/Utils/prerun/nvidiaProfileInspector.txt b/Utils/prerun/nvidiaProfileInspector.txt
new file mode 100644
index 0000000000..f022163546
--- /dev/null
+++ b/Utils/prerun/nvidiaProfileInspector.txt
@@ -0,0 +1,4 @@
+the nvidiaProfileInspector.exe has removed from shipment.
+
+you can find latest version here:
+https://github.com/Orbmu2k/nvidiaProfileInspector/releases
\ No newline at end of file
diff --git a/Utils/prerun/sha3d-example.txt b/Utils/prerun/sha3d-example.txt
new file mode 100644
index 0000000000..756a3dc2cc
--- /dev/null
+++ b/Utils/prerun/sha3d-example.txt
@@ -0,0 +1,17 @@
+REM This file will run for sha3d algo
+REM This file and nvidia inspector is disabled by default to Enable them, rename this file from sha3d-example.bat to sha3d.bat
+REM Below is a example for a 6 GPU setup
+
+SET PL=61
+SET MEMORY=-650
+SET CORE=25
+SET TEMP=90
+
+SET GPU0=-setBaseClockOffset:0,0,%CORE% -setMemoryClockOffset:0,0,%MEMORY% -setPowerTarget:0,%PL% -setTempTarget:0,0,%TEMP%
+SET GPU1=-setBaseClockOffset:1,0,%CORE% -setMemoryClockOffset:1,0,%MEMORY% -setPowerTarget:1,%PL% -setTempTarget:1,0,%TEMP%
+SET GPU2=-setBaseClockOffset:2,0,%CORE% -setMemoryClockOffset:2,0,%MEMORY% -setPowerTarget:2,%PL% -setTempTarget:2,0,%TEMP%
+SET GPU3=-setBaseClockOffset:3,0,%CORE% -setMemoryClockOffset:3,0,%MEMORY% -setPowerTarget:3,%PL% -setTempTarget:3,0,%TEMP%
+SET GPU4=-setBaseClockOffset:4,0,%CORE% -setMemoryClockOffset:4,0,%MEMORY% -setPowerTarget:4,%PL% -setTempTarget:4,0,%TEMP%
+SET GPU5=-setBaseClockOffset:5,0,%CORE% -setMemoryClockOffset:5,0,%MEMORY% -setPowerTarget:5,%PL% -setTempTarget:5,0,%TEMP%
+
+nvidiaInspector.exe %GPU0% %GPU1% %GPU2% %GPU3% %GPU4% %GPU5%
diff --git a/Utils/prerun/skein2-example.bat b/Utils/prerun/skein2-example.bat
new file mode 100644
index 0000000000..fe2498ad31
--- /dev/null
+++ b/Utils/prerun/skein2-example.bat
@@ -0,0 +1,17 @@
+REM This file will run for skein2 algo
+REM This file and nvidia inspector is disabled by default to Enable them, rename this file from skein2-example.bat to skein2.bat
+REM Below is a example for a 6 GPU setup
+
+SET PL=61
+SET MEMORY=-650
+SET CORE=25
+SET TEMP=90
+
+SET GPU0=-setBaseClockOffset:0,0,%CORE% -setMemoryClockOffset:0,0,%MEMORY% -setPowerTarget:0,%PL% -setTempTarget:0,0,%TEMP%
+SET GPU1=-setBaseClockOffset:1,0,%CORE% -setMemoryClockOffset:1,0,%MEMORY% -setPowerTarget:1,%PL% -setTempTarget:1,0,%TEMP%
+SET GPU2=-setBaseClockOffset:2,0,%CORE% -setMemoryClockOffset:2,0,%MEMORY% -setPowerTarget:2,%PL% -setTempTarget:2,0,%TEMP%
+SET GPU3=-setBaseClockOffset:3,0,%CORE% -setMemoryClockOffset:3,0,%MEMORY% -setPowerTarget:3,%PL% -setTempTarget:3,0,%TEMP%
+SET GPU4=-setBaseClockOffset:4,0,%CORE% -setMemoryClockOffset:4,0,%MEMORY% -setPowerTarget:4,%PL% -setTempTarget:4,0,%TEMP%
+SET GPU5=-setBaseClockOffset:5,0,%CORE% -setMemoryClockOffset:5,0,%MEMORY% -setPowerTarget:5,%PL% -setTempTarget:5,0,%TEMP%
+
+nvidiaInspector.exe %GPU0% %GPU1% %GPU2% %GPU3% %GPU4% %GPU5%
diff --git a/Utils/prerun/yescryptr32-example.bat b/Utils/prerun/yescryptr32-example.bat
new file mode 100644
index 0000000000..7ff5c67ef5
--- /dev/null
+++ b/Utils/prerun/yescryptr32-example.bat
@@ -0,0 +1,17 @@
+REM This file will run for yescryptr32 algo
+REM This file and nvidia inspector is disabled by default to Enable them, rename this file from yescryptr32-example.bat to yescryptr32.bat
+REM Below is a example for a 6 GPU setup
+
+SET PL=61
+SET MEMORY=650
+SET CORE=25
+SET TEMP=90
+
+SET GPU0=-setBaseClockOffset:0,0,%CORE% -setMemoryClockOffset:0,0,%MEMORY% -setPowerTarget:0,%PL% -setTempTarget:0,0,%TEMP%
+SET GPU1=-setBaseClockOffset:1,0,%CORE% -setMemoryClockOffset:1,0,%MEMORY% -setPowerTarget:1,%PL% -setTempTarget:1,0,%TEMP%
+SET GPU2=-setBaseClockOffset:2,0,%CORE% -setMemoryClockOffset:2,0,%MEMORY% -setPowerTarget:2,%PL% -setTempTarget:2,0,%TEMP%
+SET GPU3=-setBaseClockOffset:3,0,%CORE% -setMemoryClockOffset:3,0,%MEMORY% -setPowerTarget:3,%PL% -setTempTarget:3,0,%TEMP%
+SET GPU4=-setBaseClockOffset:4,0,%CORE% -setMemoryClockOffset:4,0,%MEMORY% -setPowerTarget:4,%PL% -setTempTarget:4,0,%TEMP%
+SET GPU5=-setBaseClockOffset:5,0,%CORE% -setMemoryClockOffset:5,0,%MEMORY% -setPowerTarget:5,%PL% -setTempTarget:5,0,%TEMP%
+
+nvidiaInspector.exe %GPU0% %GPU1% %GPU2% %GPU3% %GPU4% %GPU5%
diff --git a/Utils/prerun/yescryptr8g-example.bat b/Utils/prerun/yescryptr8g-example.bat
new file mode 100644
index 0000000000..fc2b321bd9
--- /dev/null
+++ b/Utils/prerun/yescryptr8g-example.bat
@@ -0,0 +1,18 @@
+
+REM This file will run for yescryptr8g algo
+REM This file and nvidia inspector is disabled by default to Enable them, rename this file from yescryptr8g-example.bat to yescryptr8g.bat
+REM Below is a example for a 6 GPU setup
+
+SET PL=61
+SET MEMORY=-500
+SET CORE=25
+SET TEMP=90
+
+SET GPU0=-setBaseClockOffset:0,0,%CORE% -setMemoryClockOffset:0,0,%MEMORY% -setPowerTarget:0,%PL% -setTempTarget:0,0,%TEMP%
+SET GPU1=-setBaseClockOffset:1,0,%CORE% -setMemoryClockOffset:1,0,%MEMORY% -setPowerTarget:1,%PL% -setTempTarget:1,0,%TEMP%
+SET GPU2=-setBaseClockOffset:2,0,%CORE% -setMemoryClockOffset:2,0,%MEMORY% -setPowerTarget:2,%PL% -setTempTarget:2,0,%TEMP%
+SET GPU3=-setBaseClockOffset:3,0,%CORE% -setMemoryClockOffset:3,0,%MEMORY% -setPowerTarget:3,%PL% -setTempTarget:3,0,%TEMP%
+SET GPU4=-setBaseClockOffset:4,0,%CORE% -setMemoryClockOffset:4,0,%MEMORY% -setPowerTarget:4,%PL% -setTempTarget:4,0,%TEMP%
+SET GPU5=-setBaseClockOffset:5,0,%CORE% -setMemoryClockOffset:5,0,%MEMORY% -setPowerTarget:5,%PL% -setTempTarget:5,0,%TEMP%
+
+nvidiaInspector.exe %GPU0% %GPU1% %GPU2% %GPU3% %GPU4% %GPU5%
diff --git a/Utils/start-windowsupdates.bat b/Utils/start-windowsupdates.bat
new file mode 100644
index 0000000000..d68c89b205
--- /dev/null
+++ b/Utils/start-windowsupdates.bat
@@ -0,0 +1,34 @@
+@echo off
+:: BatchGotAdmin
+::-------------------------------------
+REM --> Check for permissions
+>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
+
+REM --> If error flag set, we do not have admin.
+if '%errorlevel%' NEQ '0' (
+ echo Requesting administrative privileges...
+ goto UACPrompt
+) else ( goto gotAdmin )
+
+:UACPrompt
+ echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
+ set params = %*:"="
+ echo UAC.ShellExecute "cmd.exe", "/c %~s0 %params%", "", "runas", 1 >> "%temp%\getadmin.vbs"
+
+ "%temp%\getadmin.vbs"
+ del "%temp%\getadmin.vbs"
+ exit /B
+
+:gotAdmin
+ pushd "%CD%"
+ CD /D "%~dp0"
+::--------------------------------------
+
+sc config wuauserv start= auto
+net start wuauserv
+
+sc config bits start= auto
+net start bits
+
+sc config dosvc start= auto
+net start dosvc
diff --git a/Utils/stop-windowsupdates.bat b/Utils/stop-windowsupdates.bat
new file mode 100644
index 0000000000..808ee007f7
--- /dev/null
+++ b/Utils/stop-windowsupdates.bat
@@ -0,0 +1,34 @@
+@echo off
+:: BatchGotAdmin
+::-------------------------------------
+REM --> Check for permissions
+>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
+
+REM --> If error flag set, we do not have admin.
+if '%errorlevel%' NEQ '0' (
+ echo Requesting administrative privileges...
+ goto UACPrompt
+) else ( goto gotAdmin )
+
+:UACPrompt
+ echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
+ set params = %*:"="
+ echo UAC.ShellExecute "cmd.exe", "/c %~s0 %params%", "", "runas", 1 >> "%temp%\getadmin.vbs"
+
+ "%temp%\getadmin.vbs"
+ del "%temp%\getadmin.vbs"
+ exit /B
+
+:gotAdmin
+ pushd "%CD%"
+ CD /D "%~dp0"
+::--------------------------------------
+
+sc config wuauserv start= disabled
+net stop wuauserv
+
+sc config bits start= disabled
+net stop bits
+
+sc config dosvc start= disabled
+net stop dosvc
diff --git a/Version.txt b/Version.txt
new file mode 100644
index 0000000000..37ea7ef225
--- /dev/null
+++ b/Version.txt
@@ -0,0 +1,8 @@
+{
+ "Product": "NemosMiner",
+ "Version": "4.0.0.28",
+ "AutoUpdate": true,
+ "RequireRestart": true,
+ "Uri": "https://raw.githubusercontent.com/Minerx117/NemosMiner/master/Version.txt",
+ "Message": "https://github.com/Minerx117/NemosMiner/releases"
+}
diff --git a/Web/APIdocs.html b/Web/APIdocs.html
new file mode 100644
index 0000000000..2c674cfdaf
--- /dev/null
+++ b/Web/APIdocs.html
@@ -0,0 +1,323 @@
+
+
+
+
+
+
+ NemosMiner API (version 0.4.5.2)
+
+ API data is available at http://localhost:[API port]/<resource>.
+ (The default API port is 3999)
+
+ File and Scripts
+ Anything other than the resources listed below will be looked for in the web directory and sent if it exists.
+
+ Any .ps1 files in the web/scripts directory will be run and their output sent. They get passed a $Parameters object with
+ keys and values from the URL string. Test it with this demo:
+ /scripts/demo.ps1?message=Hello%20world!
+ This feature can be used to gather data that the API doesn't expose directly.
+
+ Resources
+ /algorithms
+ Shows the algorithm mappings used in Get-Algorithm to build normalized algorithm names (defined in '\Data\Algorithms.json').
+
+ /apiversion
+ Returns the version number of NemosMiner API.
+
+ /balances
+ Returns the current balance information calculated by the balance tracker.
+
+ /balancedata
+ Returns the balances collected by the balances tracker used to calculate balance information.
+
+ /brainjobs
+ Returns the brainjobs information.
+
+ /btc
+ Shows the BTC to main currency exchange rate.
+
+ /coinnames
+ Shows the Currency / CoinName mapping (defined in '\Data\CoinNames.json').
+
+ /config
+ Returns the config stored in the current config file.
+
+ /configfile
+ Returns the current config file name.
+
+ /configrunning
+ Returns the full configuration NemosMiner is currently using after all variable substitution (including 'PoolsConfig' built from the optional '.\Config\PoolsConfig.json' file).
+
+ /currency
+ Returns the main currency.
+
+ /allcurrencies
+ Returns the list of all currencies (main currency, extra currency and all currencies from balances)
+
+ /balancescurrencies
+ Returns the list of balances currencies
+
+ /dagdata
+ Returns the DAG data (Ethash & EtcHash).
+
+ /devices
+ Shows information about all mining devices.
+
+ /devices/disabled
+ Shows information about all disabled mining devices.
+
+ /devices/enabled
+ Shows information about all enabled mining devices.
+
+ /devices/unsupported
+ Shows information about all unsupported mining devices.
+
+ /displayworkers
+ Shows the rig data as reported by the monitoring server.
+
+ /driverversion
+ Returns the installed CIM & OpenCL driver version numbers.
+
+ /earningschartdata
+ Returns the data required for earnings chart.
+
+ /extracurrencies
+ Returns the list of extra currencies
+
+ /miners
+ Shows all available miners data, use for debugging.
+
+ /miners/available
+ Shows the available miners data, use for debugging.
+
+ /miners/best
+ Shows the best miners data, use for debugging.
+
+ /miners/bestminers_combo
+ Shows the bestminers_combo data, use for debugging.
+
+ /miners/mostprofitable
+ Shows the most profitable miners data, use for debugging.
+
+ /miners/disabled
+ Shows the disabled miners data, use for debugging.
+
+ /miners/failed
+ Shows the failed miners data, use for debugging.
+
+ /miners/running
+ Shows the running miners data, use for debugging.
+
+ /miners/unavailable
+ Shows the unavailable miners data, use for debugging.
+
+ /miners_device_combos
+ Shows the miners_device_combos data, use for debugging.
+
+ /miningearning
+ Shows current mining earning (in BTC).
+
+ /miningpowercost
+ Shows current mining power cost (in BTC).
+
+ /miningprofit
+ Shows current mining profit (in BTC).
+
+ /poolreasons
+ Shows all reasons why pools are unavailable.
+
+ /poolsconfig
+ Shows the pool configuration entries.
+
+ /pooldata
+ Shows pool data.
+
+ /pools
+ Shows all pool entries.
+
+ /pools/added
+ Shows the added pool entries.
+
+ /pools/available
+ Shows the available pool entries.
+
+ /pools/best
+ Shows the best pool entries.
+
+ /pools/new
+ Shows the new pool entries.
+
+ /pools/updated
+ Shows the updated pool entries.
+
+ /pools/unavailable
+ Shows the unavailable pool configuration entries.
+
+ /poolsconfigfile
+ Returns the current pools config file name.
+
+ /pools/lastearnings
+ Date & time of pools last earnings (data collected by the balances tracker).
+
+ /pools/lastused
+ Date & time when pools were last used (data is stored in '\Data\PoolsLastUsed.json').
+
+ /poolvariants
+ Shows all pool variants (defined in '\Data\PoolConfig.json').
+
+ /rates
+ Shows the current exchange rate for all configured currencies.
+
+ /regions
+ Shows the list of supported regions (defined in '\Data\Regions.json').
+
+ /regionsdata
+ Shows the region data (defined in '\Data\Regions.json').
+
+ /stats
+ Shows all stat data in the $Stats hashtable, use for debugging.
+
+ /summary
+ Shows earnings / profit summary and BTC exchange rate (as shown in the Web GUI header).
+
+ /switchinglog
+ Shows the previously executed miners.
+
+ /unprofitablealgorithms
+ Shows the list of unprofitable algorithms (defined in '\Data\UnprofitableAlgorithms.json').
+
+ /wallets
+ Shows the configured wallet data.
+
+ /watchdogexpiration
+ Shows the watchdog expiration duration (in seconds).
+
+ /watchdogtimers
+ Shows the watchdog timers.
+
+ Functions
+ Parameters look like '[url]?a=b&c=d&message=Hello%20world' (as [URI]::EscapeDataString)
+
+ /functions/api/stop
+ Stop running API instance
+ Parameters: none
+
+ "/functions/balancedata/remove
+ Remove balance data entry
+ Parameters: array of entries (JSON, entries list as array, requires properties DateTime=entry.DateTime, Pool=entry.Pool, Currency=entry.Currency, Wallet=entry.Wallet)
+ e.g.: /functions/balancedata/remove?Data=%5B{"DateTime"%3A"2021-12-22T17%3A36%3A57.5998347Z"%2C"Pool"%3A"NiceHash Internal"%2C"Currency"%3A"BTC"%2C"Wallet"%3A"33hZYX8iFg5zm9E3geqrNgeP6TMzszZk5R"}%5D?Data=%5B%7B%22DateTime%22%3A%222021-12-22T17%3A36%3A57.5998347Z%22%2C%22Pool%22%3A%22NiceHash%20Internal%22%2C%22Currency%22%3A%22BTC%22%2C%22Wallet%22%3A%2231HnYv8iFg5zm9E3g3jHgfeP6TMzszZk5R%22%7D%5D
+
+ /functions/config/device/disable
+ Opens notepad to edit current config file. Notepad will remain in foreground until notepad is closed.
+ Parameters: List of device names to disable
+ e.g.: /functions/config/device/disable=?ExcludeDeviceName=GPU%2302%2CGPU%2303?ExcludeDeviceName=GPU%2302%2CGPU%2303
+
+ /functions/config/device/enable
+ Opens notepad to edit current config file. Notepad will remain in foreground until notepad is closed.
+ Parameters: List of device names to disable
+ e.g.: /functions/config/device/enable?DeviceName=CPU%2300?DeviceName=CPU%2300
+
+ /functions/config/set
+ Write full config
+ Parameters: full config (JSON)
+ e.g.: /functions/config/set?{"Algorithm"%3A%5B""%5D%2C"BadShareRatioThreshold"%3A0.1%2C"APILogfile"%3A"c%3A%5C%5CUsers%5C%5CStephan%5C%5CDesktop%5C%5CNemosMiner%5C%5CLogs%5C%5CAPI.log"%2C"APIPort"%3A3999%2C"AutoUpdate"%3Afalse%2C"BalancesKeepAlive"%3Atrue%2C"BalancesTrackerIgnorePool"%3Anull%2C"BalancesTrackerLog"%3Afalse%2C"BalancesTrackerPollInterval"%3A10%2C"CalculatePowerCost"%3Atrue%2C"ConfigFile"%3A".%5C%5CConfig%5C%5CConfig.json"%2C"ConfigFileVersion"%3A"4.0.0.13"%2C"CPUMinerProcessPriority"%3A-2%2C"Currency"%3A"CHF"%2C"Delay"%3A0%2C"DisableDualAlgoMining"%3Afalse%2C"DisableMinerFee"%3Afalse%2C"DisableMinersWithFee"%3Afalse%2C"DisableSingleAlgoMining"%3Afalse%2C"Donate"%3A13%2C"EarningsAdjustmentFactor"%3A1%2C"ExcludeDeviceName"%3A%5B%5D%2C"ExcludeMinerName"%3A%5B""%5D%2C"ExtraCurrencies"%3A%5B"USD"%2C"ETC"%2C"mBTC"%5D%2C"GPUMinerProcessPriority"%3A-1%2C"IdlePowerUsageW"%3A60%2C"IdleSec"%3A120%2C"IgnoreMinerFee"%3Afalse%2C"IgnorePoolFee"%3Afalse%2C"IgnorePowerCost"%3Afalse%2C"SubtractBadShares"%3Atrue%2C"IncludeLegacyMiners"%3Atrue%2C"IncludeOptionalMiners"%3Atrue%2C"IncludeRegularMiners"%3Atrue%2C"Interval"%3A90%2C"LogBalanceAPIResponse"%3Afalse%2C"LogToFile"%3A%5B"Info"%2C"Warn"%2C"Error"%2C"Verbose"%2C"Debug"%5D%2C"LogToScreen"%3A%5B"Info"%2C"Warn"%2C"Error"%2C"Verbose"%2C"Debug"%5D%2C"MinAccuracy"%3A0.5%2C"MinDataSamples"%3A20%2C"MinDataSamplesAlgoMultiplier"%3A{"X16r"%3A3}%2C"MinerInstancePerDeviceModel"%3Afalse%2C"MinerSet"%3A1%2C"MinerWindowStyle"%3A"minimized"%2C"MinerWindowStyleNormalWhenBenchmarking"%3Atrue%2C"MineWhenIdle"%3Afalse%2C"MiningPoolHubAPIKey"%3A""%2C"MiningPoolHubUserName"%3A"Nemo"%2C"MinInterval"%3A0%2C"MinWorker"%3A10%2C"MonitoringServer"%3A""%2C"MonitoringUser"%3A""%2C"NiceHashAPIKey"%3A""%2C"NiceHashAPISecret"%3A""%2C"NiceHashOrganizationId"%3A""%2C"NiceHashWallet"%3A""%2C"NiceHashWalletIsInternal"%3Afalse%2C"OpenFirewallPorts"%3Atrue%2C"PayoutCurrency"%3A"BTC"%2C"PoolBalancesUpdateInterval"%3A15%2C"PoolName"%3A%5B"Blockmasters"%2C"MiningPoolHub"%2C"ZergPool"%2C"ZPool"%5D%2C"PoolsConfigFile"%3A".%5C%5CConfig%5C%5CPoolsConfig.json"%2C"PoolTimeout"%3A20%2C"PowerPricekWh"%3A{"00%3A00"%3A0.26%2C"12%3A00"%3A0.3}%2C"PowerUsage"%3A{}%2C"ProfitabilityThreshold"%3A-99%2C"ProHashingAPIKey"%3A""%2C"ProHashingMiningMode"%3A"PPS"%2C"ProHashingUserName"%3A"nemos"%2C"Proxy"%3A""%2C"Region"%3A"Europe West"%2C"ReportToServer"%3Afalse%2C"MinerSwitchingThreshold"%3A12%2C"ShowAccuracy"%3Atrue%2C"ShowAllMiners"%3Afalse%2C"ShowCoinName"%3Atrue%2C"ShowCurrency"%3Atrue%2C"ShowEarning"%3Atrue%2C"ShowEarningBias"%3Atrue%2C"ShowMinerFee"%3Atrue%2C"ShowPoolBalances"%3Afalse%2C"ShowPoolFee"%3Atrue%2C"ShowPowerCost"%3Atrue%2C"ShowPowerUsage"%3Atrue%2C"ShowProfit"%3Atrue%2C"ShowProfitBias"%3Atrue%2C"ShowWorkerStatus"%3Atrue%2C"LogViewerParameters"%3A".%5C%5CUtils%5C%5CNemosMiner_LogReader.xml"%2C"LogViewerExe"%3A".%5C%5CUtils%5C%5CSnakeTail.exe"%2C"SSL"%3Afalse%2C"StartGUIMinimized"%3Atrue%2C"StartupMode"%3A"Idle"%2C"SyncWindow"%3A3%2C"Transcript"%3Afalse%2C"UIStyle"%3A"Light"%2C"UnrealMinerEarningFactor"%3A5%2C"UnrealPoolPriceFactor"%3A1.5%2C"UseAnycast"%3Afalse%2C"UsemBTC"%3Atrue%2C"UseMinerTweaks"%3Afalse%2C"Wallets"%3A{"BTC"%3A"1QGADhdMRpp9Pk5u5zG1TrHKRrdK5R81TE"%2C"ETC"%3A"0x7CF99ec9029A98AFd385f106A93977D8105Fec0f"%2C"ETH"%3A"0x92e6F22C1493289e6AD2768E1F502Fc5b414a287"}%2C"WarmupTimes"%3A%5B0%2C15%5D%2C"Watchdog"%3Atrue%2C"WatchdogCount"%3A3%2C"WebGUI"%3Atrue%2C"WorkerName"%3A"ID%3Dtesting"}
+
+ /functions/file/edit
+ Opens notepad to edit file. Notepad will remain in foreground until notepad is closed.
+ Parameters: [String]FileName
+ e.g.: /functions/file/edit?FileName=Changelog.txt
+
+ /functions/file/showcontent
+ Shows file content in a browser window.
+ Parameters: [String]FileName
+ e.g.: /functions/file/showcontent?FileName=Changelog.txt
+
+ /functions/log/get
+ Get the last [n] lines of the log file (default 100)
+ Parameters: number of lines (optional)
+ e.g.: /functions/log/get?lines=45
+ Returns: log lines (UTF-8)
+
+ /functions/mining/getstatus
+ Get the current mining status
+ Parameters: none
+ Returns: Mining status (Idle / Paused / Running)
+
+ /functions/mining/pause
+ Pause mining (Balances Tracker & Brainjobs running, Miners stopped)
+ Parameters: none
+
+ /functions/mining/start
+ Start mining (Balances Tracker & Brainjobs running, Miners running)
+ Parameters: none
+
+ /functions/mining/stop
+ Stop mining (Balances Tracker & Brainjobs stopped, Miners stopped)
+ Parameters: none
+
+ /functions/removeorphanedminerstats
+ Remove all left over stats from miners that are no longer exist in the '\Miners' folder
+ Parameters: none
+
+ /functions/stat/get
+ Retrieve stats data
+ Parameters: Stat filter (Optional), Type=[HashRate|PowerUsage|Profit], Value=Stat.Live (If value is omitted all stat data of given type is returned)
+ e.g.: /functions/stat/get?Type=HashRate&Value=0
+ Returns: array of stats
+
+ /functions/stat/remove
+ Remove stats data
+ Parameters: Stat filter; Type=[HashRate|PowerUsage|Profit], Value=Stat.Live (If value is omitted all stat data of given type are removed)
+ e.g.: /functions/stat/remove?Type=HashRate&Value=0
+
+ /functions/stat/set
+ Set miner hashrate value (not useful for pool stats)
+ Parameters: Miner stat filter; Name=StatName, Algorithm=Algorithm(s), Type=HashRate, Value (0=failed; -1=disabled)
+ e.g.: /functions/stat/set?Miners=%5B{"Name"%3A"PhoenixMiner-v6.1b-1xRadeonRX5808GB-EtcHash%26Blake2s-40"%2C"Algorithm"%3A%5B"EtcHash"%2C"Blake2s"%5D}%5D&Type=HashRate&Value=-1
+
+ /functions/pool/enable
+ Enable disabled pool
+ Parameters: array of pools (JSON, pool list as array, requires properties Name=pool.Name, Algorithm=pool.Algorithm)
+ e.g.: /functions/pool/enable?Pools=%5B{"Name"%3A"Blockmasters"%2C"Algorithm"%3A"CpuPower"}%5D
+
+ /functions/pool/disable
+ Disable enabled pool
+ Parameters: array of pools (JSON, pool list as array, requires properties Name=pool.Name, Algorithm=pool.Algorithm)
+ e.g.: /functions/pool/disable?Pools=%5B{"Name"%3A"Blockmasters"%2C"Algorithm"%3A"CpuPower"}%5D
+
+ /functions/switchinglog/clear
+ Clear switching log data
+
+ /functions/variables/get
+ Retrieve variable value
+ Parameters: Variable name (optional, if omitted a list of all available variable is returned)
+ e.g.: /functions/variables/get?CurrentVersion
+ Returns: Variable value or variable list (JSON)
+
+ /functions/watchdogtimers/reset
+ Clear watchdog timers data
+ Parameters: none
+
+ NemosMiner.com
+
+
+
\ No newline at end of file
diff --git a/Web/balancedata.html b/Web/balancedata.html
new file mode 100644
index 0000000000..9d3df34277
--- /dev/null
+++ b/Web/balancedata.html
@@ -0,0 +1,97 @@
+
+
+
Balance Data
+
+
+ This is the balance data for the last 30 days that was collected by the balance tracker.
+
+
+ Delete entry
+
+
+
+
+
+
+
+ Date & Time
+ Pool
+ Account
+ Currency
+ Pending
+ Balance
+ Unpaid
+ Earnings
+ Delta
+ Payout
+ Paid
+ Hidden Pending
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Web/configedit.html b/Web/configedit.html
new file mode 100644
index 0000000000..ccb4bffeff
--- /dev/null
+++ b/Web/configedit.html
@@ -0,0 +1,1145 @@
+
+
+
Edit Configuration
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Web/configrunning.html b/Web/configrunning.html
new file mode 100644
index 0000000000..f6caff1edc
--- /dev/null
+++ b/Web/configrunning.html
@@ -0,0 +1,81 @@
+
+
+
Running Configuration
+
+
+ This is the full configuration NemosMiner is currently using
+ Edit Configuration File
+ Edit PoolsConfig File
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Web/css/dashboard.css b/Web/css/dashboard.css
new file mode 100644
index 0000000000..0cb5459e94
--- /dev/null
+++ b/Web/css/dashboard.css
@@ -0,0 +1,248 @@
+body {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 1rem;
+ /* zoom: 0.9; */
+}
+
+/* .detail-icon:before {
+ content: "\00B1";
+} */
+
+/*
+ * Sidebar
+ */
+.sidebar {
+ width: 260px;
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 10; /* Behind the navbar */
+ padding: 75px 0 0; /* Height of navbar */
+ box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
+}
+
+@media (min-width: 768px) {
+ .main {
+ padding-right: 35px;
+ padding-left: 290px;
+ }
+}
+
+.sidebar-sticky {
+ position: relative;
+ top: 0;
+ height: calc(110vh - 75px); /* zoom 0.9 */
+ height: calc(100vh - 75px);
+ padding-top: 1.5rem;
+ overflow-x: hidden;
+ overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
+ padding-bottom: 1.1rem;
+ padding-left: 1rem;
+}
+
+@supports ((position: -webkit-sticky) or (position: sticky)) {
+ .sidebar-sticky {
+ position: -webkit-sticky;
+ position: sticky;
+ }
+}
+
+.sidebar .nav-link {
+ font-weight: 500;
+ color: black;
+}
+
+.sidebar .nav-link .feather {
+ color: #999;
+}
+
+.sidebar .nav-link.active {
+ color: #007bff;
+}
+
+.sidebar .nav-link:hover .feather,
+.sidebar .nav-link.active .feather {
+ color: inherit;
+}
+
+.sidebar-heading {
+ font-size: 1rem;
+ text-transform: uppercase;
+}
+
+/*
+ * Content
+ */
+[role="main"] {
+ padding-top: 75px; /* Space for fixed navbar */
+}
+
+/*
+ * Navbar
+ */
+.navbar .form-control {
+ padding: 1.75rem;
+ border-width: 0;
+ border-radius: 0;
+}
+
+.navbar-brand {
+ padding-left: 2rem;
+ padding-top: 1.4rem;
+ padding-bottom: 1.4rem;
+ font-size: 1.4rem;
+}
+
+.navbar-button {
+ position: absolute;
+ left: 290px;
+}
+
+.navbar-summary {
+ position: absolute;
+ padding-top: 1.2rem;
+ padding-bottom: 1.1rem;
+ padding-right: 20px;
+ left: 770px;
+ color: white;
+ font-size: 1.2rem;
+}
+
+/*
+ * Utilities
+ */
+.border-top { border-top: 1px solid #e5e5e5; }
+.border-bottom { border-bottom: 1px solid #e5e5e5; }
+
+.column {
+ float: left;
+ width: 50%;
+}
+
+/* Clear floats after the columns */
+.row:after {
+ content: "";
+ display: table;
+ clear: both;
+}
+
+/*
+* Modal
+*/
+.modal {
+ padding: 1%;
+ top: 20%;
+ white-space: pre-wrap; /* allow \n for new line */
+}
+
+.modal-lg {
+ min-width: auto;
+ max-width: fit-content;
+}
+
+.modal-dialog {
+ overflow-y: initial !important
+}
+
+.modal-body {
+ max-height: 50vh;
+ overflow-y: auto;
+}
+
+/*
+* Form
+*/
+form .error {
+ color: #ff0000;
+ display: inline;
+}
+
+legend {
+ background-color: #d1ecf1;
+ padding: 6px 6px;
+ border-radius: 4px;
+}
+
+/*
+* Table colors
+*/
+.miner-disabled {
+ background-color: rgb(255, 241, 195);
+}
+.miner-failed {
+ background-color: rgb(255, 230, 230);
+}
+.miner-idle {
+ background-color: rgb(230, 248, 252);
+}
+.miner-running {
+ background-color: rgb(232, 250, 232);
+}
+.miner-warmingup {
+ background-color: rgb(239, 250, 239);
+}
+.miner-measuring {
+ background-color: rgb(248, 239, 223);
+}
+
+/*
+* Footer
+*/
+.footer {
+ position: fixed;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ text-align: right;
+ padding-right: 40px;
+ z-index: -1;
+}
+
+/*
+* Toggle Switch
+*/
+input[type=checkbox].toggle-switch {
+ font-size: 5px;
+ appearance: none;
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ width: 6em;
+ height: 3em;
+ border-radius: 3em;
+ background-color: #7dbcff;
+ outline: 0;
+ cursor: pointer;
+ transition: background-color 0.09s ease-in-out;
+ top: 1px;
+ position: relative;
+}
+
+input[type=checkbox].toggle-switch:checked {
+ background-color: #007bff;
+}
+
+input[type=checkbox].toggle-switch:disabled {
+ background-color: #ddd;
+}
+
+input[type=checkbox].toggle-switch::after {
+ content: '';
+ width: 3em;
+ height: 3em;
+ background-color: white;
+ border-radius: 3em;
+ position: absolute;
+ transform: scale(0.7);
+ left: 0;
+ transition: left 0.09s ease-in-out;
+ box-shadow: 0 0.1em rgba(0, 0, 0, 0.5);
+}
+
+input[type=checkbox].toggle-switch:checked::after {
+ left: 3em;
+}
+
+select {
+ height: 1.75em;
+}
\ No newline at end of file
diff --git a/Web/devices.html b/Web/devices.html
new file mode 100644
index 0000000000..64655120e7
--- /dev/null
+++ b/Web/devices.html
@@ -0,0 +1,295 @@
+
+
+
Devices
+
+ These are the devices (GPUs and CPUs) detected by NemosMiner. Configuration changes made will become active in the next cycle.
+
+
+ Disable Device
+
+
+ Enabled Devices
+
+
+
+
+
+
+ Name
+ Vendor
+ Model
+ Type
+ Status
+ Memory
+ Cores/Stream Processors
+ Clock Speed
+ Driver Version (CIM)
+ Driver Version (OpenCL)
+ CUDA Version
+ Configured Power Usage
+ PCI Bus Id
+ Bus_Index
+ Bus_Type_Index
+ Bus_Vendor_Index
+ Bus_Platform_Index
+ Id
+ Index
+ PlatformId
+ PlatformId_Index
+ Slot
+ Type_Id
+ Type_Index
+ Type_PlatformId_Index
+ Type_Slot
+ Type_Vendor_Id
+ Type_Vendor_Index
+ Type_Vendor_Slot
+ Vendor_Id
+ Vendor_Index
+ Vendor_Slot
+ State
+
+
+
+
+ Disabled Devices
+
+
+ Enable Device
+
+
+
+
+
+
+
+ Name
+ Vendor
+ Model
+ Type
+ Status
+ Memory
+ Cores/Stream Processors
+ Clock Speed
+ Driver Version (CIM)
+ Driver Version (OpenCL)
+ CUDA Version
+ Configured Power Usage
+ PCI Bus Id
+ Bus_Index
+ Bus_Type_Index
+ Bus_Vendor_Index
+ Bus_Platform_Index
+ Id
+ Index
+ PlatformId
+ PlatformId_Index
+ Slot
+ Type_Id
+ Type_Index
+ Type_PlatformId_Index
+ Type_Slot
+ Type_Vendor_Id
+ Type_Vendor_Index
+ Type_Vendor_Slot
+ Vendor_Id
+ Vendor_Index
+ Vendor_Slot
+ State
+
+
+
+
+
+
Unsupported Devices
+
+
+
+
+
+
+ Name
+ Vendor
+ Model
+ Type
+ Memory
+ Cores/Stream Processors
+ Clock Speed
+ Driver Version (CIM)
+ Driver Version (OpenCL)
+ CUDA Version
+ Configured Power Usage
+ PCI Bus Id
+ Bus_Index
+ Bus_Type_Index
+ Bus_Vendor_Index
+ Bus_Platform_Index
+ Id
+ Index
+ PlatformId
+ PlatformId_Index
+ Slot
+ Type_Id
+ Type_Index
+ Type_PlatformId_Index
+ Type_Slot
+ Type_Vendor_Id
+ Type_Vendor_Index
+ Type_Vendor_Slot
+ Vendor_Id
+ Vendor_Index
+ Vendor_Slot
+ State
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Web/earningschart.html b/Web/earningschart.html
new file mode 100644
index 0000000000..386a5bee9a
--- /dev/null
+++ b/Web/earningschart.html
@@ -0,0 +1,201 @@
+
+
+
Earnings Chart
+
+
+ Consolidated earnings of the last 30 active mining days The data is taken from the pools APIs and may not yet include results from recent mining
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Web/index.html b/Web/index.html
new file mode 100644
index 0000000000..641bde636a
--- /dev/null
+++ b/Web/index.html
@@ -0,0 +1,483 @@
+
+
+
Dashboard
+
+
+
+ Re-benchmark
+ Re-measure Power Usage
+ Mark as failed
+ Disable
+
+
+ Launched Miners
+
+
+
+
+
+
+ Name
+ Devices
+ Type
+ Status
+ Earning
+ Earning Bias
+ Profit
+ Profit Bias
+ Power Cost
+ Power Usage
+ Primary Algorithm
+ Live Hashrate
+ Benchmarked Hashrate
+ Primary Pool
+ Primary Pool Fee
+ Primary Algorithm Miner Fee
+ Secondary Algorithm
+ Live Hashrate
+ Benchmarked Hashrate
+ Secondary Pool
+ Secondary Pool Fee
+ Secondary Algorithm Miner Fee
+ Total Mining Duration
+ WarmupTimes
+ Environment Variables
+ API Port
+ Best
+ Activated
+ New
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Web/js/utilities.js b/Web/js/utilities.js
new file mode 100644
index 0000000000..66682dca97
--- /dev/null
+++ b/Web/js/utilities.js
@@ -0,0 +1,222 @@
+// fix bootstrap-table icons
+window.icons = {
+ refresh: 'fa-sync',
+ toggle: 'fa-id-card',
+ columns: 'fa-columns',
+ clear: 'fa-trash'
+};
+
+function formatMiners(data) {
+ // This function can alter the returned data before building the table, formatting it in a way
+ // that is easier to display and manipulate in a table
+ $.each(data, function(index, item) {
+ // Format miner link
+ if (item.MinerUri) item.tName = "" + item.Name + " ";
+ else item.tName = item.Name;
+
+ // Format the device(s)
+ if (item.DeviceName) item.tDevices = item.DeviceName.toString();
+ else item.tDevices = '';
+
+ // Format the algorithm data
+ if (item.Algorithm.length > 0) item.tPrimaryAlgorithm = item.Algorithm[0];
+ else item.tPrimaryAlgorithm = "";
+ if (item.Algorithm.length > 1) item.tSecondaryAlgorithm = item.Algorithm[1];
+ else item.tSecondaryAlgorithm = "";
+
+ // Format the pool data
+ if (item.Workers.length > 0) {
+ item.tPrimaryMinerFee = item.Workers[0].Fee;
+ item.tPrimarySpeed = item.Workers[0].Speed;
+ if (item.Workers[0].Pool) {
+ item.tPrimaryPool = item.Workers[0].Pool.Name;
+ item.tPrimaryPoolFee = item.Workers[0].Pool.Fee;
+ }
+ }
+ else {
+ item.tSecondaryMinerFee = '';
+ item.tPrimaryPool = '';
+ item.tPrimaryPoolFee = '';
+ }
+
+ if (item.Workers.length > 1) {
+ item.tSecondarySpeed = item.Workers[1].Speed;
+ item.tSecondaryMinerFee = item.Workers[1].Fee;
+ if (item.Workers[1].Pool) {
+ item.tSecondaryPool = item.Workers[1].Pool.Name;
+ item.tSecondaryPoolFee = item.Workers[1].Pool.Fee;
+ }
+ }
+ else {
+ item.tSecondaryMinerFee = '';
+ item.tSecondaryPool = '';
+ item.tSecondaryPoolFee = '';
+ }
+
+ // Format margin of error
+ item.tEarningAccuracy = formatPercent(item.Earning_Accuracy);
+
+ // Format the live speed(s)
+ if (item.Speed_Live) {
+ if (item.Speed_Live.length > 0) item.tPrimarySpeedLive = item.Speed_Live[0];
+ if (item.Speed_Live.length > 1) item.tSecondarySpeedLive = item.Speed_Live[1];
+ }
+
+ // Format Total Mining Duration (TimeSpan)
+ item.tTotalMiningDuration = formatTimeSpan(item.TotalMiningDuration);
+
+ // Format status
+ const enumstatus = ["Running", "Idle", "Failed", "Disabled"];
+ item.tStatus = enumstatus[item.Status];
+ });
+ return data;
+}
+
+function formatTimeSince(value) {
+ var value = (new Date).getTime() - (new Date(value)).getTime();
+ var localtime = new Date().getTime();
+ var lastupdated = '';
+ if (isNaN(value)) value = localtime - parseInt(kicked.replace("/Date(", "").replace(")/", ""));
+
+ seconds = value / 1000;
+ lastupdated = formatTime(seconds)
+
+ if (lastupdated == '') return 'just now';
+ else return lastupdated.trim() + ' ago';
+}
+
+function formatTime(seconds) {
+ var formattedtime = "";
+
+ interval = Math.floor(seconds / (24 * 3600));
+ if (interval > 1) formattedtime = formattedtime + interval.toString() + ' days ';
+ else if (interval == 1) formattedtime = formattedtime + interval.toString() + ' day ';
+
+ if (interval > 0) seconds = seconds - interval * (24 * 3600);
+ interval = Math.floor(seconds / 3600);
+ if (interval > 1) formattedtime = formattedtime + interval.toString() + ' hours ';
+ else if (interval == 1) formattedtime = formattedtime + interval.toString() + ' hour ';
+
+ if (interval > 0) seconds = seconds - interval * 3600;
+ interval = Math.floor(seconds / 60);
+ if (interval > 1) formattedtime = formattedtime + interval.toString() + ' minutes ';
+ else if (interval == 1) formattedtime = formattedtime + interval.toString() + ' minute ';
+
+ if (interval > 0) seconds = seconds - interval * 60;
+ interval = parseInt(seconds % 60);
+ if (interval > 1) formattedtime = formattedtime + interval.toString() + ' seconds ';
+ else if (interval == 1) formattedtime = formattedtime + interval.toString() + ' second ';
+
+ return formattedtime.trim()
+}
+
+function formatHashrateValue(value) {
+ if (value == null) return ''
+ if (value === 0) return '0 H/s'
+ if (value > 0) {
+ if (value <= 1) return value.toFixed(2) + ' H/s';
+ else {
+ var sizes = ['H/s', 'kH/s', 'MH/s', 'GH/s', 'TH/s', 'PH/s', 'EH/s', 'ZH/s', 'YH/s'];
+ var i = Math.floor(Math.log(value) / Math.log(1000));
+ return parseFloat((value / Math.pow(1000, i)).toFixed(2)) + ' ' + sizes[i];
+ }
+ }
+ return 'N/A';
+};
+
+function formatHashrate(value) {
+ const values = value.split(' ')
+ return values.map(formatHashrate).toString();
+}
+
+function formatmBTC(value) {
+ if (value == null) return ''
+ if (value > 0) return parseFloat(value * rates / 1000).toFixed(8);
+ if (value == 0) return (0).toFixed(8);
+ if (value < 0) return parseFloat(value * rate / 1000).toFixed(8);
+ return 'N/A';
+};
+
+function formatBTC(value) {
+ if (value == null) return ''
+ if (value > 0) return parseFloat(value * rate).toFixed(8);
+ if (value == 0) return (0).toFixed(8);
+ if (value < 0) return parseFloat(value * rate).toFixed(8);
+ return 'N/A';
+};
+
+function formatDate(value) {
+ if (value === '') return "N/A";
+ if (Date.parse(value)) return (new Date(value).toLocaleString(navigator.language));
+ if (value == "Unknown") return "N/A";
+ if (value == null) return "N/A";
+ return value;
+};
+
+function formatWatt(value) {
+ if (value == 0) return (0).toFixed(2) + ' W';
+ if (value > 0) return parseFloat(value).toFixed(2) + ' W';
+ return 'N/A';
+};
+
+function formatPercent(value) {
+ if (value === 0) return '0.00 %';
+ if (parseFloat(value)) return parseFloat(value * 100).toFixed(2) + ' %';
+ return '';
+};
+
+function formatPrices(value) {
+ if (value > 0) return (value * 1000000000).toFixed(10);
+ return '';
+};
+
+function formatArrayAsString(value) {
+ if (value === '') return ''
+ if (value == null) return '';
+ return value.sort().join('; ');
+};
+
+
+function formatDigits3(value) {
+ if (value > 0) return (value).toFixed(3);
+ return '';
+};
+
+function detailFormatter(index, row) {
+ var html = [];
+ $.each(row, function (key, value) {
+ if (typeof value === 'string') html.push(`${key}: ${JSON.stringify(value).replaceAll("\\\\", "\\")}
`);
+ else html.push(`${key}: ${JSON.stringify(value)}
`);
+ });
+ return html.join('');
+}
+
+function formatBytes(bytes) {
+ if (bytes > 0) {
+ decimals = 2;
+ var k = 1024;
+ dm = decimals || 2;
+ sizes = ['Bytes', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
+ i = Math.floor(Math.log(bytes) / Math.log(k));
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
+ }
+ return '-';
+}
+
+function formatTimeSpan(timespan) {
+ var duration = '-';
+ if (timespan) {
+ duration = timespan.Days + ' days ';
+ duration = duration + timespan.Hours + ' hrs ';
+ duration = duration + timespan.Minutes + ' min ';
+ duration = duration + timespan.Seconds + ' sec ';
+ }
+ return duration;
+}
+
+function createUUID() {
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+ var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
+ return v.toString(16);
+ });
+}
\ No newline at end of file
diff --git a/Web/logviewer.html b/Web/logviewer.html
new file mode 100644
index 0000000000..7afda82bc1
--- /dev/null
+++ b/Web/logviewer.html
@@ -0,0 +1,47 @@
+
+
+
System Log
+
+
+ Shows the last lines of the NemosMiner log
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Web/miners.html b/Web/miners.html
new file mode 100644
index 0000000000..141dedabf1
--- /dev/null
+++ b/Web/miners.html
@@ -0,0 +1,236 @@
+
+
+
All Miners
+
+
+ These are all miners. Note: NemosMiner will only create miners for algorithms that have at least one available pool.
+
+
+ Re-benchmark
+ Re-measure Power Usage
+ Mark as failed
+ Disable
+
+
+
+
+
+
+
+ Name
+ BaseName
+ Version
+ CommandLine
+ Devices
+ Type
+ Status
+ Reason
+ Earning Bias
+ Earning
+ Profit Bias
+ Profit
+ Power Cost
+ Power Usage
+ Total Mining Duration
+ Accuracy
+ Primary Algorithm
+ Primary Hashrate
+ Primary Pool
+ Primary Pool Fee
+ Primary Algorithm Miner Fee
+ Secondary Algorithm
+ Secondary Hashrate
+ Secondary Pool
+ Secondary Pool Fee
+ Secondary Algorithm Miner Fee
+ Miner API
+ API Port
+ Min. Data Samples
+ WarmupTimes
+ Environment Variables
+ Activated
+ WindowStyle
+ Available
+ Benchmark
+ Measure PowerUsage
+ Best
+ Most Profitable
+ Disabled
+ Restart
+ Keep Running
+ Prioritize
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Web/minersmostprofitable.html b/Web/minersmostprofitable.html
new file mode 100644
index 0000000000..47c9a50c99
--- /dev/null
+++ b/Web/minersmostprofitable.html
@@ -0,0 +1,232 @@
+
+
+
Most Profitable Miners
+
+
+ These are the most profitable miners per algorithm and device.
+
+
+ Re-benchmark
+ Re-measure Power Usage
+ Mark as failed
+ Disable
+
+
+
+
+
+
+
+ Name
+ BaseName
+ Version
+ CommandLine
+ Devices
+ Type
+ Status
+ Earning Bias
+ Earning
+ Profit Bias
+ Profit
+ Power Cost
+ Power Usage
+ Total Mining Duration
+ Accuracy
+ Primary Algorithm
+ Primary Hashrate
+ Primary Pool
+ Primary Pool Fee
+ Primary Algorithm Miner Fee
+ Secondary Algorithm
+ Secondary Hashrate
+ Secondary Pool
+ Secondary Pool Fee
+ Secondary Algorithm Miner Fee
+ Miner API
+ API Port
+ Min. Data Samples
+ WarmupTimes
+ Environment Variables
+ Activated
+ WindowStyle
+ Benchmark
+ Best
+ Disabled
+ Restart
+ Keep Running
+ Prioritize
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Web/minersunavailable.html b/Web/minersunavailable.html
new file mode 100644
index 0000000000..9a70c95ba8
--- /dev/null
+++ b/Web/minersunavailable.html
@@ -0,0 +1,259 @@
+
+
+
Unavailable Miners
+
+
+ These are all unavailable miners. The column 'Reason' shows the filter criteria(s) that made the miner unavailable.
+
+
+ Re-benchmark
+ Re-measure Power Usage
+ Remove Watchdog
+ Mark as failed
+ Disable
+
+
+
+
+
+
+
+ Name
+ BaseName
+ Version
+ CommandLine
+ Devices
+ Type
+ Status
+ Reason
+ Earning Bias
+ Earning
+ Profit Bias
+ Profit
+ Power Cost
+ Power Usage
+ Total Mining Duration
+ Accuracy
+ Primary Algorithm
+ Primary Hashrate
+ Primary Pool
+ Primary Pool Fee
+ Primary Algorithm Miner Fee
+ Secondary Algorithm
+ Secondary Hashrate
+ Secondary Pool
+ Secondary Pool Fee
+ Secondary Algorithm Miner Fee
+ Miner API
+ API Port
+ Min. Data Samples
+ WarmupTimes
+ Environment Variables
+ Activated
+ WindowStyle
+ Benchmark
+ Best
+ Most Profitable
+ Disabled
+ Restart
+ Keep Running
+ Prioritize
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Web/parts/foot.html b/Web/parts/foot.html
new file mode 100644
index 0000000000..dd5dff7f73
--- /dev/null
+++ b/Web/parts/foot.html
@@ -0,0 +1,72 @@
+
+
+
+
+