Improve mining pool interface, added GoBrrr pool, Public Pool and Satoshi Radio pool
This commit is contained in:
parent
f613c7e9a1
commit
aeee5238b3
19 changed files with 274 additions and 26 deletions
|
@ -12,6 +12,8 @@ public:
|
|||
PoolStats parseResponse(const JsonDocument &doc) const override;
|
||||
LogoData getLogo() const override;
|
||||
bool supportsDailyEarnings() const override { return true; }
|
||||
bool hasLogo() const override { return true; }
|
||||
std::string getDisplayLabel() const override { return "BRAIINS/POOL"; } // Fallback if needed
|
||||
std::string getDailyEarningsLabel() const override { return "sats/earned"; }
|
||||
private:
|
||||
static int getHashrateMultiplier(const std::string &unit);
|
||||
|
|
14
src/lib/mining_pool/gobrrr_pool/gobrrr_pool.cpp
Normal file
14
src/lib/mining_pool/gobrrr_pool/gobrrr_pool.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
// src/noderunners/noderunners_pool.cpp
|
||||
#include "gobrrr_pool.hpp"
|
||||
|
||||
std::string GoBrrrPool::getApiUrl() const {
|
||||
return "https://pool.gobrrr.me/api/client/" + poolUser;
|
||||
}
|
||||
|
||||
LogoData GoBrrrPool::getLogo() const {
|
||||
return LogoData {
|
||||
.data = epd_icons_allArray[7],
|
||||
.width = 122,
|
||||
.height = 122
|
||||
};
|
||||
}
|
15
src/lib/mining_pool/gobrrr_pool/gobrrr_pool.hpp
Normal file
15
src/lib/mining_pool/gobrrr_pool/gobrrr_pool.hpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "lib/mining_pool/mining_pool_interface.hpp"
|
||||
#include "lib/mining_pool/public_pool/public_pool.hpp"
|
||||
|
||||
#include <icons/icons.h>
|
||||
|
||||
class GoBrrrPool : public PublicPool {
|
||||
public:
|
||||
std::string getApiUrl() const override;
|
||||
bool hasLogo() const override { return true; }
|
||||
std::string getDisplayLabel() const override { return "GOBRRR/POOL"; }
|
||||
LogoData getLogo() const override;
|
||||
};
|
|
@ -12,7 +12,9 @@ public:
|
|||
virtual void prepareRequest(HTTPClient& http) const = 0;
|
||||
virtual std::string getApiUrl() const = 0;
|
||||
virtual PoolStats parseResponse(const JsonDocument& doc) const = 0;
|
||||
virtual bool hasLogo() const = 0;
|
||||
virtual LogoData getLogo() const = 0;
|
||||
virtual std::string getDisplayLabel() const = 0;
|
||||
virtual bool supportsDailyEarnings() const = 0;
|
||||
virtual std::string getDailyEarningsLabel() const = 0;
|
||||
|
||||
|
|
122
src/lib/mining_pool/mining_pool_stats_handler.cpp
Normal file
122
src/lib/mining_pool/mining_pool_stats_handler.cpp
Normal file
|
@ -0,0 +1,122 @@
|
|||
#include "mining_pool_stats_handler.hpp"
|
||||
#include <iostream>
|
||||
|
||||
std::array<std::string, NUM_SCREENS> parseMiningPoolStatsHashRate(std::string text, const MiningPoolInterface& pool)
|
||||
{
|
||||
std::array<std::string, NUM_SCREENS> ret;
|
||||
ret.fill(""); // Initialize all elements to empty strings
|
||||
std::string hashrate;
|
||||
std::string label;
|
||||
|
||||
if (text.length() > 21) {
|
||||
// We are massively future-proof!!
|
||||
label = "ZH/S";
|
||||
hashrate = text.substr(0, text.length() - 21);
|
||||
} else if (text.length() > 18) {
|
||||
label = "EH/S";
|
||||
hashrate = text.substr(0, text.length() - 18);
|
||||
} else if (text.length() > 15) {
|
||||
label = "PH/S";
|
||||
hashrate = text.substr(0, text.length() - 15);
|
||||
} else if (text.length() > 12) {
|
||||
label = "TH/S";
|
||||
hashrate = text.substr(0, text.length() - 12);
|
||||
} else if (text.length() > 9) {
|
||||
label = "GH/S";
|
||||
hashrate = text.substr(0, text.length() - 9);
|
||||
} else if (text.length() > 6) {
|
||||
label = "MH/S";
|
||||
hashrate = text.substr(0, text.length() - 6);
|
||||
} else if (text.length() > 3) {
|
||||
label = "KH/S";
|
||||
hashrate = text.substr(0, text.length() - 3);
|
||||
} else {
|
||||
label = "H/S";
|
||||
hashrate = text;
|
||||
}
|
||||
|
||||
std::size_t textLength = hashrate.length();
|
||||
|
||||
// Calculate the position where the digits should start
|
||||
// Account for the position of the mining pool logo and the hashrate label
|
||||
std::size_t startIndex = NUM_SCREENS - 1 - textLength;
|
||||
|
||||
// Insert the pickaxe icon just before the digits
|
||||
if (startIndex > 0)
|
||||
{
|
||||
ret[startIndex - 1] = "mdi:pickaxe";
|
||||
}
|
||||
|
||||
// Place the digits
|
||||
for (std::size_t i = 0; i < textLength; ++i)
|
||||
{
|
||||
ret[startIndex + i] = hashrate.substr(i, 1);
|
||||
}
|
||||
|
||||
ret[NUM_SCREENS - 1] = label;
|
||||
|
||||
if (pool.hasLogo()) {
|
||||
ret[0] = "mdi:miningpool";
|
||||
} else {
|
||||
ret[0] = pool.getDisplayLabel();
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::array<std::string, NUM_SCREENS> parseMiningPoolStatsDailyEarnings(int sats, std::string label, const MiningPoolInterface& pool)
|
||||
{
|
||||
std::array<std::string, NUM_SCREENS> ret;
|
||||
ret.fill(""); // Initialize all elements to empty strings
|
||||
std::string satsDisplay = std::to_string(sats);
|
||||
|
||||
if (sats >= 100000000) {
|
||||
// A whale mining 1+ BTC per day! No decimal points; whales scoff at such things.
|
||||
label = "BTC" + label.substr(4);
|
||||
satsDisplay = satsDisplay.substr(0, satsDisplay.length() - 8);
|
||||
} else if (sats >= 10000000) {
|
||||
// 10.0M to 99.9M you get one decimal point
|
||||
satsDisplay = satsDisplay.substr(0, satsDisplay.length() - 6) + "." + satsDisplay[2] + "M";
|
||||
} else if (sats >= 1000000) {
|
||||
// 1.00M to 9.99M you get two decimal points
|
||||
satsDisplay = satsDisplay.substr(0, satsDisplay.length() - 6) + "." + satsDisplay.substr(2, 2) + "M";
|
||||
} else if (sats >= 100000) {
|
||||
// 100K to 999K you get no extra precision
|
||||
satsDisplay = satsDisplay.substr(0, satsDisplay.length() - 3) + "K";
|
||||
} else if (sats >= 10000) {
|
||||
// 10.0K to 99.9K you get one decimal point
|
||||
satsDisplay = satsDisplay.substr(0, satsDisplay.length() - 3) + "." + satsDisplay[2] + "K";
|
||||
} else {
|
||||
// Pleb miner! 4 digit or fewer sats will fit as-is. no-op.
|
||||
}
|
||||
|
||||
std::size_t textLength = satsDisplay.length();
|
||||
|
||||
// Calculate the position where the digits should start
|
||||
// Account for the position of the mining pool logo
|
||||
std::size_t startIndex = NUM_SCREENS - 1 - textLength;
|
||||
|
||||
// Insert the pickaxe icon just before the digits if there's room
|
||||
if (startIndex > 0)
|
||||
{
|
||||
ret[startIndex - 1] = "mdi:pickaxe";
|
||||
}
|
||||
|
||||
// Place the digits
|
||||
for (std::size_t i = 0; i < textLength; ++i)
|
||||
{
|
||||
ret[startIndex + i] = satsDisplay.substr(i, 1);
|
||||
}
|
||||
|
||||
ret[NUM_SCREENS - 1] = label;
|
||||
|
||||
if (pool.hasLogo()) {
|
||||
ret[0] = "mdi:miningpool";
|
||||
} else {
|
||||
ret[0] = pool.getDisplayLabel();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
8
src/lib/mining_pool/mining_pool_stats_handler.hpp
Normal file
8
src/lib/mining_pool/mining_pool_stats_handler.hpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <array>
|
||||
#include <string>
|
||||
#ifndef UNITY_TEST
|
||||
#include "lib/mining_pool/mining_pool_interface.hpp"
|
||||
#endif
|
||||
|
||||
std::array<std::string, NUM_SCREENS> parseMiningPoolStatsHashRate(std::string text, const MiningPoolInterface& pool);
|
||||
std::array<std::string, NUM_SCREENS> parseMiningPoolStatsDailyEarnings(int sats, std::string label, const MiningPoolInterface& pool);
|
|
@ -1,15 +1,15 @@
|
|||
// src/noderunners/noderunners_pool.cpp
|
||||
#include "noderunners_pool.hpp"
|
||||
|
||||
void NodeRunnersPool::prepareRequest(HTTPClient& http) const {
|
||||
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 {
|
||||
PoolStats NoderunnersPool::parseResponse(const JsonDocument& doc) const {
|
||||
std::string hashrateStr = doc["hashrate1m"].as<std::string>();
|
||||
char unit = hashrateStr.back();
|
||||
std::string value = hashrateStr.substr(0, hashrateStr.size() - 1);
|
||||
|
@ -22,7 +22,7 @@ PoolStats NodeRunnersPool::parseResponse(const JsonDocument& doc) const {
|
|||
};
|
||||
}
|
||||
|
||||
LogoData NodeRunnersPool::getLogo() const {
|
||||
LogoData NoderunnersPool::getLogo() const {
|
||||
return LogoData {
|
||||
.data = epd_icons_allArray[6],
|
||||
.width = 122,
|
||||
|
@ -30,7 +30,10 @@ LogoData NodeRunnersPool::getLogo() const {
|
|||
};
|
||||
}
|
||||
|
||||
int NodeRunnersPool::getHashrateMultiplier(char unit) {
|
||||
int NoderunnersPool::getHashrateMultiplier(char unit) {
|
||||
if (unit == '0')
|
||||
return 0;
|
||||
|
||||
static const std::unordered_map<char, int> multipliers = {
|
||||
{'Z', 21}, {'E', 18}, {'P', 15}, {'T', 12},
|
||||
{'G', 9}, {'M', 6}, {'K', 3}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "lib/mining_pool/mining_pool_interface.hpp"
|
||||
#include <icons/icons.h>
|
||||
|
||||
class NodeRunnersPool : public MiningPoolInterface {
|
||||
class NoderunnersPool : public MiningPoolInterface {
|
||||
public:
|
||||
void setPoolUser(const std::string& user) override { poolUser = user; }
|
||||
|
||||
|
@ -14,7 +14,9 @@ public:
|
|||
LogoData getLogo() const override;
|
||||
bool supportsDailyEarnings() const override { return false; }
|
||||
std::string getDailyEarningsLabel() const override { return ""; }
|
||||
bool hasLogo() const override { return true; }
|
||||
std::string getDisplayLabel() const override { return "NODE/RUNNERS"; } // Fallback if needed
|
||||
|
||||
private:
|
||||
protected:
|
||||
static int getHashrateMultiplier(char unit);
|
||||
};
|
|
@ -10,6 +10,9 @@ public:
|
|||
std::string getApiUrl() const override;
|
||||
PoolStats parseResponse(const JsonDocument& doc) const override;
|
||||
LogoData getLogo() const override;
|
||||
bool hasLogo() const override { return true; }
|
||||
std::string getDisplayLabel() const override { return "OCEAN/POOL"; } // Fallback if needed
|
||||
bool supportsDailyEarnings() const override { return true; }
|
||||
std::string getDailyEarningsLabel() const override { return "sats/block"; }
|
||||
|
||||
};
|
|
@ -1,15 +1,20 @@
|
|||
#include "pool_factory.hpp"
|
||||
|
||||
|
||||
const char* PoolFactory::MINING_POOL_NAME_OCEAN = "ocean";
|
||||
const char* PoolFactory::MINING_POOL_NAME_NODERUNNERS = "noderunners";
|
||||
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";
|
||||
|
||||
std::unique_ptr<MiningPoolInterface> PoolFactory::createPool(const std::string& poolName) {
|
||||
static const std::unordered_map<std::string, std::function<std::unique_ptr<MiningPoolInterface>()>> poolFactories = {
|
||||
{MINING_POOL_NAME_OCEAN, []() { return std::make_unique<OceanPool>(); }},
|
||||
{MINING_POOL_NAME_NODERUNNERS, []() { return std::make_unique<NodeRunnersPool>(); }},
|
||||
{MINING_POOL_NAME_BRAIINS, []() { return std::make_unique<BraiinsPool>(); }}
|
||||
{MINING_POOL_NAME_NODERUNNERS, []() { return std::make_unique<NoderunnersPool>(); }},
|
||||
{MINING_POOL_NAME_BRAIINS, []() { return std::make_unique<BraiinsPool>(); }},
|
||||
{MINING_POOL_NAME_SATOSHI_RADIO, []() { return std::make_unique<SatoshiRadioPool>(); }},
|
||||
{MINING_POOL_NAME_PUBLIC_POOL, []() { return std::make_unique<PublicPool>(); }},
|
||||
{MINING_POOL_NAME_GOBRRR_POOL, []() { return std::make_unique<GoBrrrPool>(); }}
|
||||
};
|
||||
|
||||
auto it = poolFactories.find(poolName);
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
#include "noderunners/noderunners_pool.hpp"
|
||||
#include "braiins/brains_pool.hpp"
|
||||
#include "ocean/ocean_pool.hpp"
|
||||
#include "satoshi_radio/satoshi_radio_pool.hpp"
|
||||
#include "public_pool/public_pool.hpp"
|
||||
#include "gobrrr_pool/gobrrr_pool.hpp"
|
||||
|
||||
class PoolFactory {
|
||||
public:
|
||||
|
@ -13,7 +16,10 @@ class PoolFactory {
|
|||
return {
|
||||
MINING_POOL_NAME_OCEAN,
|
||||
MINING_POOL_NAME_NODERUNNERS,
|
||||
MINING_POOL_NAME_BRAIINS
|
||||
MINING_POOL_NAME_SATOSHI_RADIO,
|
||||
MINING_POOL_NAME_BRAIINS,
|
||||
MINING_POOL_NAME_PUBLIC_POOL,
|
||||
MINING_POOL_NAME_GOBRRR_POOL
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -32,4 +38,7 @@ class PoolFactory {
|
|||
static const char* MINING_POOL_NAME_OCEAN;
|
||||
static const char* MINING_POOL_NAME_NODERUNNERS;
|
||||
static const char* MINING_POOL_NAME_BRAIINS;
|
||||
static const char* MINING_POOL_NAME_SATOSHI_RADIO;
|
||||
static const char* MINING_POOL_NAME_PUBLIC_POOL;
|
||||
static const char* MINING_POOL_NAME_GOBRRR_POOL;
|
||||
};
|
21
src/lib/mining_pool/public_pool/public_pool.cpp
Normal file
21
src/lib/mining_pool/public_pool/public_pool.cpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
// src/noderunners/noderunners_pool.cpp
|
||||
#include "public_pool.hpp"
|
||||
|
||||
std::string PublicPool::getApiUrl() const {
|
||||
return "https://public-pool.io:40557/api/client/" + poolUser;
|
||||
}
|
||||
|
||||
PoolStats PublicPool::parseResponse(const JsonDocument& doc) const {
|
||||
uint64_t totalHashrate = 0;
|
||||
|
||||
for (JsonVariantConst worker : doc["workers"].as<JsonArrayConst>()) {
|
||||
totalHashrate += static_cast<uint64_t>(std::llround(worker["hashRate"].as<double>()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
return PoolStats{
|
||||
.hashrate = std::to_string(totalHashrate),
|
||||
.dailyEarnings = std::nullopt // Public Pool doesn't support daily earnings
|
||||
};
|
||||
}
|
15
src/lib/mining_pool/public_pool/public_pool.hpp
Normal file
15
src/lib/mining_pool/public_pool/public_pool.hpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "lib/mining_pool/mining_pool_interface.hpp"
|
||||
#include "lib/mining_pool/noderunners/noderunners_pool.hpp"
|
||||
|
||||
#include <icons/icons.h>
|
||||
|
||||
class PublicPool : public NoderunnersPool {
|
||||
public:
|
||||
std::string getApiUrl() const override;
|
||||
bool hasLogo() const override { return false; }
|
||||
std::string getDisplayLabel() const override { return "PUBLIC/POOL"; }
|
||||
PoolStats parseResponse(const JsonDocument& doc) const override;
|
||||
};
|
6
src/lib/mining_pool/satoshi_radio/satoshi_radio_pool.cpp
Normal file
6
src/lib/mining_pool/satoshi_radio/satoshi_radio_pool.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
// src/noderunners/noderunners_pool.cpp
|
||||
#include "satoshi_radio_pool.hpp"
|
||||
|
||||
std::string SatoshiRadioPool::getApiUrl() const {
|
||||
return "https://pool.satoshiradio.nl/api/v1/users/" + poolUser;
|
||||
}
|
14
src/lib/mining_pool/satoshi_radio/satoshi_radio_pool.hpp
Normal file
14
src/lib/mining_pool/satoshi_radio/satoshi_radio_pool.hpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "lib/mining_pool/mining_pool_interface.hpp"
|
||||
#include "lib/mining_pool/noderunners/noderunners_pool.hpp"
|
||||
|
||||
#include <icons/icons.h>
|
||||
|
||||
class SatoshiRadioPool : public NoderunnersPool {
|
||||
public:
|
||||
std::string getApiUrl() const override;
|
||||
bool hasLogo() const override { return false; }
|
||||
std::string getDisplayLabel() const override { return "SATOSHI/RADIO"; } // Fallback if needed
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue