diff --git a/src/lib/mining_pool/braiins/brains_pool.cpp b/src/lib/mining_pool/braiins/brains_pool.cpp index 47b6e61..6449b29 100644 --- a/src/lib/mining_pool/braiins/brains_pool.cpp +++ b/src/lib/mining_pool/braiins/brains_pool.cpp @@ -1,32 +1,43 @@ #include "brains_pool.hpp" -void BraiinsPool::prepareRequest(HTTPClient& http) const { +void BraiinsPool::prepareRequest(HTTPClient &http) const +{ http.addHeader("Pool-Auth-Token", poolUser.c_str()); } -std::string BraiinsPool::getApiUrl() const { +std::string BraiinsPool::getApiUrl() const +{ return "https://pool.braiins.com/accounts/profile/json/btc/"; } PoolStats BraiinsPool::parseResponse(const JsonDocument &doc) const { - if (doc["btc"].isNull()) { + try + { + if (doc["btc"].isNull()) + { + return PoolStats{ + .hashrate = "0", + .dailyEarnings = 0}; + } + + std::string unit = doc["btc"]["hash_rate_unit"].as(); + + static const std::unordered_map multipliers = { + {"Zh/s", 21}, {"Eh/s", 18}, {"Ph/s", 15}, {"Th/s", 12}, {"Gh/s", 9}, {"Mh/s", 6}, {"Kh/s", 3}}; + + int multiplier = multipliers.at(unit); + float hashValue = doc["btc"]["hash_rate_5m"].as(); + + return PoolStats{ + .hashrate = std::to_string(static_cast(std::round(hashValue))) + std::string(multiplier, '0'), + .dailyEarnings = static_cast(doc["btc"]["today_reward"].as() * 100000000)}; + } + catch (const std::exception &e) + { + Serial.printf("Error parsing %s response: %s\n", getPoolName().c_str(), e.what()); return PoolStats{ .hashrate = "0", - .dailyEarnings = 0 - }; + .dailyEarnings = std::nullopt}; } - - std::string unit = doc["btc"]["hash_rate_unit"].as(); - - static const std::unordered_map multipliers = { - {"Zh/s", 21}, {"Eh/s", 18}, {"Ph/s", 15}, {"Th/s", 12}, {"Gh/s", 9}, {"Mh/s", 6}, {"Kh/s", 3}}; - - int multiplier = multipliers.at(unit); - float hashValue = doc["btc"]["hash_rate_5m"].as(); - - return PoolStats{ - .hashrate = std::to_string(static_cast(std::round(hashValue))) + std::string(multiplier, '0'), - .dailyEarnings = static_cast(doc["btc"]["today_reward"].as() * 100000000)}; } - diff --git a/src/lib/mining_pool/ckpool/ckpool.cpp b/src/lib/mining_pool/ckpool/ckpool.cpp new file mode 100644 index 0000000..4c17c7d --- /dev/null +++ b/src/lib/mining_pool/ckpool/ckpool.cpp @@ -0,0 +1,47 @@ +#include "ckpool.hpp" + +void CKPool::prepareRequest(HTTPClient &http) const +{ + // Empty as CKPool doesn't need special headers +} + +std::string CKPool::getApiUrl() const +{ + return getBaseUrl() + "/users/" + poolUser; +} + +PoolStats CKPool::parseResponse(const JsonDocument &doc) const +{ + try + { + std::string hashrateStr = doc["hashrate1m"].as(); + + // Special case for "0" + if (hashrateStr == "0") { + return PoolStats{ + .hashrate = "0", + .dailyEarnings = std::nullopt + }; + } + + char unit = hashrateStr.back(); + std::string value = hashrateStr.substr(0, hashrateStr.size() - 1); + + int multiplier = getHashrateMultiplier(unit); + double hashrate = std::stod(value) * std::pow(10, multiplier); + + char buffer[32]; + snprintf(buffer, sizeof(buffer), "%.0f", hashrate); + + return PoolStats{ + .hashrate = buffer, + .dailyEarnings = std::nullopt}; + } + catch (const std::exception &e) + { + Serial.printf("Error parsing %s response: %s\n", getPoolName().c_str(), e.what()); + return PoolStats{ + .hashrate = "0", + .dailyEarnings = std::nullopt}; + } +} \ No newline at end of file diff --git a/src/lib/mining_pool/ckpool/ckpool.hpp b/src/lib/mining_pool/ckpool/ckpool.hpp new file mode 100644 index 0000000..bbf75d1 --- /dev/null +++ b/src/lib/mining_pool/ckpool/ckpool.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "lib/mining_pool/mining_pool_interface.hpp" +#include + +class CKPool : public MiningPoolInterface { +public: + void setPoolUser(const std::string& user) override { poolUser = user; } + + void prepareRequest(HTTPClient& http) const override; + std::string getApiUrl() const override; + PoolStats parseResponse(const JsonDocument& doc) const override; + bool supportsDailyEarnings() const override { return false; } + std::string getDailyEarningsLabel() const override { return ""; } + bool hasLogo() const override { return false; } + std::string getDisplayLabel() const override { return "CK/POOL"; } + std::string getPoolName() const override { + return "ckpool"; + } + +protected: + virtual std::string getBaseUrl() const { + return "https://solo.ckpool.org"; + } +}; \ No newline at end of file diff --git a/src/lib/mining_pool/ckpool/eu_ckpool.hpp b/src/lib/mining_pool/ckpool/eu_ckpool.hpp new file mode 100644 index 0000000..95a9b75 --- /dev/null +++ b/src/lib/mining_pool/ckpool/eu_ckpool.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "ckpool.hpp" + +class EUCKPool : public CKPool { +public: + std::string getDisplayLabel() const override { return "CK/POOL"; } + std::string getPoolName() const override { + return "eu_ckpool"; + } + +protected: + std::string getBaseUrl() const override { + return "https://eusolo.ckpool.org"; + } +}; \ No newline at end of file diff --git a/src/lib/mining_pool/noderunners/noderunners_pool.cpp b/src/lib/mining_pool/noderunners/noderunners_pool.cpp index da34e38..e7e10ca 100644 --- a/src/lib/mining_pool/noderunners/noderunners_pool.cpp +++ b/src/lib/mining_pool/noderunners/noderunners_pool.cpp @@ -1,27 +1,48 @@ // src/noderunners/noderunners_pool.cpp #include "noderunners_pool.hpp" -void NoderunnersPool::prepareRequest(HTTPClient& http) const { - // Empty as NodeRunners doesn't need special headers +void NoderunnersPool::prepareRequest(HTTPClient &http) const +{ + // Empty as Noderunners doesn't need special headers } -std::string NoderunnersPool::getApiUrl() const { +std::string NoderunnersPool::getApiUrl() const +{ return "https://pool.noderunners.network/api/v1/users/" + poolUser; } -PoolStats NoderunnersPool::parseResponse(const JsonDocument& doc) const { - std::string hashrateStr = doc["hashrate1m"].as(); - char unit = hashrateStr.back(); - std::string value = hashrateStr.substr(0, hashrateStr.size() - 1); - - int multiplier = getHashrateMultiplier(unit); - double hashrate = std::stod(value) * std::pow(10, multiplier); - - char buffer[32]; - snprintf(buffer, sizeof(buffer), "%.0f", hashrate); - - return PoolStats{ - .hashrate = buffer, - .dailyEarnings = std::nullopt - }; +PoolStats NoderunnersPool::parseResponse(const JsonDocument &doc) const +{ + try + { + std::string hashrateStr = doc["hashrate1m"].as(); + + // Special case for "0" + if (hashrateStr == "0") { + return PoolStats{ + .hashrate = "0", + .dailyEarnings = std::nullopt + }; + } + + char unit = hashrateStr.back(); + std::string value = hashrateStr.substr(0, hashrateStr.size() - 1); + + int multiplier = getHashrateMultiplier(unit); + double hashrate = std::stod(value) * std::pow(10, multiplier); + + char buffer[32]; + snprintf(buffer, sizeof(buffer), "%.0f", hashrate); + + return PoolStats{ + .hashrate = buffer, + .dailyEarnings = std::nullopt}; + } + catch (const std::exception &e) + { + Serial.printf("Error parsing %s response: %s\n", getPoolName().c_str(), e.what()); + return PoolStats{ + .hashrate = "0", + .dailyEarnings = std::nullopt}; + } } \ No newline at end of file diff --git a/src/lib/mining_pool/ocean/ocean_pool.cpp b/src/lib/mining_pool/ocean/ocean_pool.cpp index f6050af..cf9bf49 100644 --- a/src/lib/mining_pool/ocean/ocean_pool.cpp +++ b/src/lib/mining_pool/ocean/ocean_pool.cpp @@ -1,18 +1,29 @@ #include "ocean_pool.hpp" -void OceanPool::prepareRequest(HTTPClient& http) const { +void OceanPool::prepareRequest(HTTPClient &http) const +{ // Empty as Ocean doesn't need special headers } -std::string OceanPool::getApiUrl() const { +std::string OceanPool::getApiUrl() const +{ return "https://api.ocean.xyz/v1/statsnap/" + poolUser; } -PoolStats OceanPool::parseResponse(const JsonDocument& doc) const { - return PoolStats{ - .hashrate = doc["result"]["hashrate_300s"].as(), - .dailyEarnings = static_cast( - doc["result"]["estimated_earn_next_block"].as() * 100000000 - ) - }; -} +PoolStats OceanPool::parseResponse(const JsonDocument &doc) const +{ + try + { + return PoolStats{ + .hashrate = doc["result"]["hashrate_300s"].as(), + .dailyEarnings = static_cast( + doc["result"]["estimated_earn_next_block"].as() * 100000000)}; + } + catch (const std::exception &e) + { + Serial.printf("Error parsing %s response: %s\n", getPoolName().c_str(), e.what()); + return PoolStats{ + .hashrate = "0", + .dailyEarnings = std::nullopt}; + } +} \ No newline at end of file diff --git a/src/lib/mining_pool/pool_factory.cpp b/src/lib/mining_pool/pool_factory.cpp index 150793a..c353996 100644 --- a/src/lib/mining_pool/pool_factory.cpp +++ b/src/lib/mining_pool/pool_factory.cpp @@ -6,6 +6,8 @@ const char* PoolFactory::MINING_POOL_NAME_BRAIINS = "braiins"; const char* PoolFactory::MINING_POOL_NAME_SATOSHI_RADIO = "satoshi_radio"; const char* PoolFactory::MINING_POOL_NAME_PUBLIC_POOL = "public_pool"; const char* PoolFactory::MINING_POOL_NAME_GOBRRR_POOL = "gobrrr_pool"; +const char* PoolFactory::MINING_POOL_NAME_CKPOOL = "ckpool"; +const char* PoolFactory::MINING_POOL_NAME_EU_CKPOOL = "eu_ckpool"; const char* PoolFactory::LOGOS_DIR = "/logos"; std::unique_ptr PoolFactory::createPool(const std::string& poolName) { @@ -15,7 +17,9 @@ std::unique_ptr PoolFactory::createPool(const std::string& {MINING_POOL_NAME_BRAIINS, []() { return std::make_unique(); }}, {MINING_POOL_NAME_SATOSHI_RADIO, []() { return std::make_unique(); }}, {MINING_POOL_NAME_PUBLIC_POOL, []() { return std::make_unique(); }}, - {MINING_POOL_NAME_GOBRRR_POOL, []() { return std::make_unique(); }} + {MINING_POOL_NAME_GOBRRR_POOL, []() { return std::make_unique(); }}, + {MINING_POOL_NAME_CKPOOL, []() { return std::make_unique(); }}, + {MINING_POOL_NAME_EU_CKPOOL, []() { return std::make_unique(); }} }; auto it = poolFactories.find(poolName); diff --git a/src/lib/mining_pool/pool_factory.hpp b/src/lib/mining_pool/pool_factory.hpp index 96231c9..951dbe5 100644 --- a/src/lib/mining_pool/pool_factory.hpp +++ b/src/lib/mining_pool/pool_factory.hpp @@ -11,6 +11,8 @@ #include "satoshi_radio/satoshi_radio_pool.hpp" #include "public_pool/public_pool.hpp" #include "gobrrr_pool/gobrrr_pool.hpp" +#include "ckpool/ckpool.hpp" +#include "ckpool/eu_ckpool.hpp" #include #include @@ -26,7 +28,9 @@ class PoolFactory { MINING_POOL_NAME_SATOSHI_RADIO, MINING_POOL_NAME_BRAIINS, MINING_POOL_NAME_PUBLIC_POOL, - MINING_POOL_NAME_GOBRRR_POOL + MINING_POOL_NAME_GOBRRR_POOL, + MINING_POOL_NAME_CKPOOL, + MINING_POOL_NAME_EU_CKPOOL }; } @@ -52,5 +56,7 @@ class PoolFactory { static const char* MINING_POOL_NAME_SATOSHI_RADIO; static const char* MINING_POOL_NAME_PUBLIC_POOL; static const char* MINING_POOL_NAME_GOBRRR_POOL; + static const char* MINING_POOL_NAME_CKPOOL; + static const char* MINING_POOL_NAME_EU_CKPOOL; static const char* LOGOS_DIR; }; \ No newline at end of file diff --git a/src/lib/mining_pool/public_pool/public_pool.cpp b/src/lib/mining_pool/public_pool/public_pool.cpp index 9a5d56f..8c7c6e2 100644 --- a/src/lib/mining_pool/public_pool/public_pool.cpp +++ b/src/lib/mining_pool/public_pool/public_pool.cpp @@ -1,21 +1,32 @@ // src/noderunners/noderunners_pool.cpp #include "public_pool.hpp" -std::string PublicPool::getApiUrl() const { +std::string PublicPool::getApiUrl() const +{ return "https://public-pool.io:40557/api/client/" + poolUser; } -PoolStats PublicPool::parseResponse(const JsonDocument& doc) const { +PoolStats PublicPool::parseResponse(const JsonDocument &doc) const +{ uint64_t totalHashrate = 0; - - for (JsonVariantConst worker : doc["workers"].as()) { - totalHashrate += static_cast(std::llround(worker["hashRate"].as())); - } - + try + { + for (JsonVariantConst worker : doc["workers"].as()) + { + totalHashrate += static_cast(std::llround(worker["hashRate"].as())); + } + } + catch (const std::exception &e) + { + Serial.printf("Error parsing %s response: %s\n", getPoolName().c_str(), e.what()); + return PoolStats{ + .hashrate = "0", + .dailyEarnings = std::nullopt}; + } return PoolStats{ .hashrate = std::to_string(totalHashrate), - .dailyEarnings = std::nullopt // Public Pool doesn't support daily earnings + .dailyEarnings = std::nullopt // Public Pool doesn't support daily earnings }; } \ No newline at end of file diff --git a/src/lib/mining_pool/satoshi_radio/satoshi_radio_pool.cpp b/src/lib/mining_pool/satoshi_radio/satoshi_radio_pool.cpp index 5b8f4a3..39fa107 100644 --- a/src/lib/mining_pool/satoshi_radio/satoshi_radio_pool.cpp +++ b/src/lib/mining_pool/satoshi_radio/satoshi_radio_pool.cpp @@ -1,6 +1,7 @@ // src/noderunners/noderunners_pool.cpp #include "satoshi_radio_pool.hpp" -std::string SatoshiRadioPool::getApiUrl() const { +std::string SatoshiRadioPool::getApiUrl() const +{ return "https://pool.satoshiradio.nl/api/v1/users/" + poolUser; }