Big refactor of mining pool support, optimization of existing icons

This commit is contained in:
Djuri 2024-12-20 01:08:03 +01:00
parent f9aa593f0b
commit 814cd234a9
23 changed files with 772 additions and 1190 deletions

View file

@ -0,0 +1,32 @@
#include "brains_pool.hpp"
void BraiinsPool::prepareRequest(HTTPClient& http) const {
http.addHeader("Pool-Auth-Token", poolUser.c_str());
}
std::string BraiinsPool::getApiUrl() const {
return "https://pool.braiins.com/accounts/profile/json/btc/";
}
PoolStats BraiinsPool::parseResponse(const JsonDocument &doc) const
{
std::string unit = doc["btc"]["hash_rate_unit"].as<std::string>();
static const std::unordered_map<std::string, int> 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<float>();
return PoolStats{
.hashrate = std::to_string(static_cast<int>(std::round(hashValue))) + std::string(multiplier, '0'),
.dailyEarnings = static_cast<int64_t>(doc["btc"]["today_reward"].as<float>() * 100000000)};
}
LogoData BraiinsPool::getLogo() const {
return LogoData{
.data = epd_icons_allArray[5],
.width = 122,
.height = 250
};
}

View file

@ -0,0 +1,18 @@
#pragma once
#include "lib/mining_pool/mining_pool_interface.hpp"
#include <icons/icons.h>
class BraiinsPool : 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;
LogoData getLogo() const override;
bool supportsDailyEarnings() const override { return true; }
std::string getDailyEarningsLabel() const override { return "sats/earned"; }
private:
static int getHashrateMultiplier(const std::string &unit);
};

View file

@ -0,0 +1,10 @@
#pragma once
#include <cstdint>
#include <stddef.h>
struct LogoData {
const uint8_t* data;
size_t width;
size_t height;
};

View file

@ -0,0 +1,21 @@
#pragma once
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "pool_stats.hpp"
#include "logo_data.hpp"
class MiningPoolInterface {
public:
virtual ~MiningPoolInterface() = default;
virtual void setPoolUser(const std::string& user) = 0;
virtual void prepareRequest(HTTPClient& http) const = 0;
virtual std::string getApiUrl() const = 0;
virtual PoolStats parseResponse(const JsonDocument& doc) const = 0;
virtual LogoData getLogo() const = 0;
virtual bool supportsDailyEarnings() const = 0;
virtual std::string getDailyEarningsLabel() const = 0;
protected:
std::string poolUser;
};

View file

@ -0,0 +1,39 @@
// src/noderunners/noderunners_pool.cpp
#include "noderunners_pool.hpp"
void NodeRunnersPool::prepareRequest(HTTPClient& http) const {
// Empty as NodeRunners doesn't need special headers
}
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<std::string>();
char unit = hashrateStr.back();
std::string value = hashrateStr.substr(0, hashrateStr.size() - 1);
int multiplier = getHashrateMultiplier(unit);
return PoolStats{
.hashrate = value + std::string(multiplier, '0'),
.dailyEarnings = std::nullopt
};
}
LogoData NodeRunnersPool::getLogo() const {
return LogoData {
.data = epd_icons_allArray[6],
.width = 122,
.height = 122
};
}
int NodeRunnersPool::getHashrateMultiplier(char unit) {
static const std::unordered_map<char, int> multipliers = {
{'Z', 21}, {'E', 18}, {'P', 15}, {'T', 12},
{'G', 9}, {'M', 6}, {'K', 3}
};
return multipliers.at(unit);
}

View file

@ -0,0 +1,20 @@
#pragma once
#include "lib/mining_pool/mining_pool_interface.hpp"
#include <icons/icons.h>
class NodeRunnersPool : 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;
LogoData getLogo() const override;
bool supportsDailyEarnings() const override { return false; }
std::string getDailyEarningsLabel() const override { return ""; }
private:
static int getHashrateMultiplier(char unit);
};

View file

@ -0,0 +1,26 @@
#include "ocean_pool.hpp"
void OceanPool::prepareRequest(HTTPClient& http) const {
// Empty as Ocean doesn't need special headers
}
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<std::string>(),
.dailyEarnings = static_cast<int64_t>(
doc["result"]["estimated_earn_next_block"].as<float>() * 100000000
)
};
}
LogoData OceanPool::getLogo() const {
return LogoData{
.data = epd_icons_allArray[4],
.width = 122,
.height = 122
};
}

View file

@ -0,0 +1,15 @@
#pragma once
#include "lib/mining_pool/mining_pool_interface.hpp"
#include <icons/icons.h>
class OceanPool : 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;
LogoData getLogo() const override;
bool supportsDailyEarnings() const override { return true; }
std::string getDailyEarningsLabel() const override { return "sats/block"; }
};

View file

@ -0,0 +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";
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>(); }}
};
auto it = poolFactories.find(poolName);
if (it == poolFactories.end()) {
return nullptr;
}
return it->second();
}

View file

@ -0,0 +1,35 @@
#pragma once
#include "mining_pool_interface.hpp"
#include <memory>
#include <string>
#include "noderunners/noderunners_pool.hpp"
#include "braiins/brains_pool.hpp"
#include "ocean/ocean_pool.hpp"
class PoolFactory {
public:
static std::unique_ptr<MiningPoolInterface> createPool(const std::string& poolName);
static std::vector<std::string> getAvailablePools() {
return {
MINING_POOL_NAME_OCEAN,
MINING_POOL_NAME_NODERUNNERS,
MINING_POOL_NAME_BRAIINS
};
}
static std::string getAvailablePoolsAsString() {
const auto pools = getAvailablePools();
std::string result;
for (size_t i = 0; i < pools.size(); ++i) {
result += pools[i];
if (i < pools.size() - 1) {
result += ", ";
}
}
return result;
}
private:
static const char* MINING_POOL_NAME_OCEAN;
static const char* MINING_POOL_NAME_NODERUNNERS;
static const char* MINING_POOL_NAME_BRAIINS;
};

View file

@ -0,0 +1,10 @@
#pragma once
#include <string>
#include <optional>
struct PoolStats {
std::string hashrate;
std::optional<int64_t> dailyEarnings;
};