Compare commits
3 commits
main
...
feature/ln
Author | SHA1 | Date | |
---|---|---|---|
a87374fc67 | |||
7cd4c8dd37 | |||
19c877a254 |
12 changed files with 706 additions and 212 deletions
|
@ -4,24 +4,22 @@
|
||||||
#include <emscripten/bind.h>
|
#include <emscripten/bind.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
char getCurrencySymbol(char input)
|
char getCurrencySymbol(char input)
|
||||||
{
|
{
|
||||||
switch (input)
|
switch (input)
|
||||||
{
|
{
|
||||||
case CURRENCY_EUR:
|
case CURRENCY_EUR:
|
||||||
return '[';
|
return '[';
|
||||||
break;
|
|
||||||
case CURRENCY_GBP:
|
case CURRENCY_GBP:
|
||||||
return ']';
|
return ']';
|
||||||
break;
|
|
||||||
case CURRENCY_JPY:
|
case CURRENCY_JPY:
|
||||||
return '^';
|
return '^';
|
||||||
break;
|
// Dollar symbol currencies
|
||||||
case CURRENCY_AUD:
|
case CURRENCY_AUD:
|
||||||
case CURRENCY_CAD:
|
case CURRENCY_CAD:
|
||||||
case CURRENCY_USD:
|
case CURRENCY_USD:
|
||||||
return '$';
|
return '$';
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
@ -33,21 +31,18 @@ std::string getCurrencyCode(char input)
|
||||||
{
|
{
|
||||||
case CURRENCY_EUR:
|
case CURRENCY_EUR:
|
||||||
return CURRENCY_CODE_EUR;
|
return CURRENCY_CODE_EUR;
|
||||||
break;
|
|
||||||
case CURRENCY_GBP:
|
case CURRENCY_GBP:
|
||||||
return CURRENCY_CODE_GBP;
|
return CURRENCY_CODE_GBP;
|
||||||
break;
|
|
||||||
case CURRENCY_JPY:
|
case CURRENCY_JPY:
|
||||||
return CURRENCY_CODE_JPY;
|
return CURRENCY_CODE_JPY;
|
||||||
break;
|
|
||||||
case CURRENCY_AUD:
|
case CURRENCY_AUD:
|
||||||
return CURRENCY_CODE_AUD;
|
return CURRENCY_CODE_AUD;
|
||||||
break;
|
|
||||||
case CURRENCY_CAD:
|
case CURRENCY_CAD:
|
||||||
return CURRENCY_CODE_CAD;
|
return CURRENCY_CODE_CAD;
|
||||||
break;
|
case CURRENCY_USD:
|
||||||
default:
|
|
||||||
return CURRENCY_CODE_USD;
|
return CURRENCY_CODE_USD;
|
||||||
|
default:
|
||||||
|
return CURRENCY_CODE_UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,126 +58,255 @@ char getCurrencyChar(const std::string& input)
|
||||||
return CURRENCY_AUD;
|
return CURRENCY_AUD;
|
||||||
else if (input == "CAD")
|
else if (input == "CAD")
|
||||||
return CURRENCY_CAD;
|
return CURRENCY_CAD;
|
||||||
|
else if (input == "USD")
|
||||||
|
return CURRENCY_USD;
|
||||||
|
else if (input == "ALL")
|
||||||
|
return CURRENCY_ALL;
|
||||||
|
else if (input == "BWP")
|
||||||
|
return CURRENCY_BWP;
|
||||||
|
else if (input == "HNL")
|
||||||
|
return CURRENCY_HNL;
|
||||||
|
else if (input == "HTG")
|
||||||
|
return CURRENCY_HTG;
|
||||||
|
else if (input == "MWK")
|
||||||
|
return CURRENCY_MWK;
|
||||||
|
else if (input == "MZN")
|
||||||
|
return CURRENCY_MZN;
|
||||||
|
else if (input == "NAD")
|
||||||
|
return CURRENCY_NAD;
|
||||||
|
else if (input == "PYG")
|
||||||
|
return CURRENCY_PYG;
|
||||||
|
else if (input == "RON")
|
||||||
|
return CURRENCY_RON;
|
||||||
|
else if (input == "SZL")
|
||||||
|
return CURRENCY_SZL;
|
||||||
|
else if (input == "ZAR")
|
||||||
|
return CURRENCY_ZAR;
|
||||||
|
else if (input == "ZMW")
|
||||||
|
return CURRENCY_ZMW;
|
||||||
|
// Map dollar-symbol currencies to USD character code
|
||||||
|
else if (input == "NZD" || input == "SGD" || input == "HKD" ||
|
||||||
|
input == "BND" || input == "FJD" || input == "SBD" ||
|
||||||
|
input == "TTD" || input == "XCD" || input == "KYD" ||
|
||||||
|
input == "GYD" || input == "BBD" || input == "BSD" ||
|
||||||
|
input == "BMD" || input == "LRD" || input == "ZWL" ||
|
||||||
|
input == "ARS" || input == "CLP" || input == "COP" ||
|
||||||
|
input == "MXN" || input == "UYU" || input == "DOP" ||
|
||||||
|
input == "SVC" || input == "SRD")
|
||||||
|
return CURRENCY_USD;
|
||||||
else
|
else
|
||||||
return CURRENCY_USD; // Assuming USD is the default for unknown inputs
|
return ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char currencySymbol, bool useSuffixFormat, bool mowMode, bool shareDot)
|
// Private helper methods
|
||||||
{
|
namespace {
|
||||||
std::array<std::string, NUM_SCREENS> ret;
|
std::array<std::string, NUM_SCREENS> formatPriceData(std::uint32_t price, char currencySymbol, const std::string& currencyCode, bool useSuffixFormat, bool mowMode, bool shareDot, bool useSymbol)
|
||||||
std::string priceString;
|
|
||||||
if (std::to_string(price).length() >= NUM_SCREENS || useSuffixFormat)
|
|
||||||
{
|
{
|
||||||
int numScreens = shareDot || mowMode ? NUM_SCREENS - 1 : NUM_SCREENS - 2;
|
std::array<std::string, NUM_SCREENS> ret;
|
||||||
priceString = getCurrencySymbol(currencySymbol) + formatNumberWithSuffix(price, numScreens, mowMode);
|
std::string priceString;
|
||||||
}
|
// If useSymbol is true, we're using the char version - use symbol as requested
|
||||||
else
|
// If useSymbol is false, we're using the string version - only use symbol if it's a recognized currency
|
||||||
{
|
bool shouldUseSymbol = useSymbol || (!useSymbol && currencySymbol != ' ');
|
||||||
priceString = getCurrencySymbol(currencySymbol) + std::to_string(price);
|
|
||||||
}
|
|
||||||
std::uint32_t firstIndex = 0;
|
|
||||||
if ((shareDot && priceString.length() <= (NUM_SCREENS)) || priceString.length() < (NUM_SCREENS))
|
|
||||||
{
|
|
||||||
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
|
||||||
|
|
||||||
if (mowMode)
|
if (std::to_string(price).length() >= NUM_SCREENS || useSuffixFormat)
|
||||||
{
|
{
|
||||||
ret[0] = "MOW/UNITS";
|
int numScreens = shareDot || mowMode ? NUM_SCREENS - 1 : NUM_SCREENS - 2;
|
||||||
|
if (shouldUseSymbol) {
|
||||||
|
priceString = getCurrencySymbol(currencySymbol) + formatNumberWithSuffix(price, numScreens, mowMode);
|
||||||
|
} else {
|
||||||
|
priceString = formatNumberWithSuffix(price, numScreens, mowMode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret[0] = "BTC/" + getCurrencyCode(currencySymbol);
|
if (shouldUseSymbol) {
|
||||||
}
|
priceString = getCurrencySymbol(currencySymbol) + std::to_string(price);
|
||||||
|
} else {
|
||||||
|
priceString = std::to_string(price);
|
||||||
firstIndex = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t dotPosition = priceString.find('.');
|
|
||||||
|
|
||||||
if (shareDot && dotPosition != std::string::npos && dotPosition > 0)
|
|
||||||
{
|
|
||||||
std::vector<std::string> tempArray;
|
|
||||||
if (dotPosition != std::string::npos && dotPosition > 0)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < priceString.length(); ++i)
|
|
||||||
{
|
|
||||||
if (i == dotPosition - 1)
|
|
||||||
{
|
|
||||||
tempArray.push_back(std::string(1, priceString[i]) + ".");
|
|
||||||
++i; // Skip the dot in the next iteration
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tempArray.push_back(std::string(1, priceString[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy from tempArray to ret
|
|
||||||
for (std::uint32_t i = firstIndex; i < NUM_SCREENS && i - firstIndex < tempArray.size(); ++i)
|
|
||||||
{
|
|
||||||
ret[i] = tempArray[i - firstIndex];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
std::uint32_t firstIndex = 0;
|
||||||
else
|
if ((shareDot && priceString.length() <= (NUM_SCREENS)) || priceString.length() < (NUM_SCREENS))
|
||||||
{
|
|
||||||
for (std::uint32_t i = firstIndex; i < NUM_SCREENS; i++)
|
|
||||||
{
|
|
||||||
ret[i] = std::string(1, priceString[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price,char currencySymbol, bool withSatsSymbol)
|
|
||||||
{
|
|
||||||
std::array<std::string, NUM_SCREENS> ret;
|
|
||||||
std::string priceString = std::to_string(int(round(1 / float(price) * 10e7)));
|
|
||||||
std::uint32_t firstIndex = 0;
|
|
||||||
std::uint8_t insertSatSymbol = NUM_SCREENS - priceString.length() - 1;
|
|
||||||
|
|
||||||
if (priceString.length() < (NUM_SCREENS))
|
|
||||||
{
|
|
||||||
// Check if price is greater than 1 billion
|
|
||||||
if (price >= 100000000)
|
|
||||||
{
|
|
||||||
double satsPerCurrency = (1.0 / static_cast<double>(price)) * 1e8; // Calculate satoshis
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << std::fixed << std::setprecision(3) << satsPerCurrency; // Format with 3 decimal places
|
|
||||||
priceString = oss.str();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
priceString = std::to_string(static_cast<int>(round(1.0 / static_cast<double>(price) * 1e8))); // Default formatting
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pad the string with spaces if necessary
|
|
||||||
if (priceString.length() < NUM_SCREENS)
|
|
||||||
{
|
{
|
||||||
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
||||||
|
|
||||||
|
if (mowMode)
|
||||||
|
{
|
||||||
|
ret[0] = "MOW/UNITS";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret[0] = "BTC/" + currencyCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
firstIndex = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currencySymbol != CURRENCY_USD || price >= 100000000) // no time anymore when earlier than 1
|
size_t dotPosition = priceString.find('.');
|
||||||
ret[0] = "SATS/" + getCurrencyCode(currencySymbol);
|
|
||||||
|
if (shareDot && dotPosition != std::string::npos && dotPosition > 0)
|
||||||
|
{
|
||||||
|
std::vector<std::string> tempArray;
|
||||||
|
if (dotPosition != std::string::npos && dotPosition > 0)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < priceString.length(); ++i)
|
||||||
|
{
|
||||||
|
if (i == dotPosition - 1)
|
||||||
|
{
|
||||||
|
tempArray.push_back(std::string(1, priceString[i]) + ".");
|
||||||
|
++i; // Skip the dot in the next iteration
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tempArray.push_back(std::string(1, priceString[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy from tempArray to ret
|
||||||
|
for (std::uint32_t i = firstIndex; i < NUM_SCREENS && i - firstIndex < tempArray.size(); ++i)
|
||||||
|
{
|
||||||
|
ret[i] = tempArray[i - firstIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ret[0] = "MSCW/TIME";
|
|
||||||
|
|
||||||
firstIndex = 1;
|
|
||||||
|
|
||||||
for (std::uint32_t i = firstIndex; i < NUM_SCREENS; i++)
|
|
||||||
{
|
{
|
||||||
ret[i] = priceString[i];
|
for (std::uint32_t i = firstIndex; i < NUM_SCREENS; i++)
|
||||||
|
{
|
||||||
|
ret[i] = std::string(1, priceString[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (withSatsSymbol)
|
return ret;
|
||||||
{
|
|
||||||
ret[insertSatSymbol] = "STS";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
|
std::array<std::string, NUM_SCREENS> formatSatsPerCurrency(std::uint32_t price, char currencySymbol, const std::string& currencyCode, bool withSatsSymbol, bool alwaysShowSats)
|
||||||
|
{
|
||||||
|
std::array<std::string, NUM_SCREENS> ret;
|
||||||
|
double satsPerCurrency = (1.0 / static_cast<double>(price)) * 1e8;
|
||||||
|
std::string priceString;
|
||||||
|
|
||||||
|
// Handle values below 1 sat per currency with 3 decimal places
|
||||||
|
if (satsPerCurrency < 1.0) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << std::fixed << std::setprecision(3) << satsPerCurrency;
|
||||||
|
priceString = oss.str();
|
||||||
|
}
|
||||||
|
// // Check if price is greater than 1 billion (for displaying with 3 decimal places)
|
||||||
|
// else if (price >= 100000000) {
|
||||||
|
// std::ostringstream oss;
|
||||||
|
// oss << std::fixed << std::setprecision(3) << satsPerCurrency;
|
||||||
|
// priceString = oss.str();
|
||||||
|
// }
|
||||||
|
else {
|
||||||
|
// Default formatting for integer values
|
||||||
|
priceString = std::to_string(static_cast<int>(round(satsPerCurrency)));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t firstIndex = 0;
|
||||||
|
std::uint8_t insertSatSymbol = NUM_SCREENS - priceString.length() - 1;
|
||||||
|
|
||||||
|
if (priceString.length() < (NUM_SCREENS))
|
||||||
|
{
|
||||||
|
// Pad the string with spaces if necessary
|
||||||
|
if (priceString.length() < NUM_SCREENS)
|
||||||
|
{
|
||||||
|
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alwaysShowSats || currencySymbol != CURRENCY_USD || price >= 100000000) // no time anymore when earlier than 1
|
||||||
|
ret[0] = "SATS/" + currencyCode;
|
||||||
|
else
|
||||||
|
ret[0] = "MSCW/TIME";
|
||||||
|
|
||||||
|
firstIndex = 1;
|
||||||
|
|
||||||
|
for (std::uint32_t i = firstIndex; i < NUM_SCREENS; i++)
|
||||||
|
{
|
||||||
|
ret[i] = priceString[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (withSatsSymbol)
|
||||||
|
{
|
||||||
|
ret[insertSatSymbol] = "STS";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<std::string, NUM_SCREENS> formatMarketCap(std::uint32_t blockHeight, std::uint32_t price, char currencySymbol, const std::string& currencyCode, bool bigChars)
|
||||||
|
{
|
||||||
|
std::array<std::string, NUM_SCREENS> ret;
|
||||||
|
std::uint32_t firstIndex = 0;
|
||||||
|
double supply = getSupplyAtBlock(blockHeight);
|
||||||
|
uint64_t marketCap = static_cast<std::uint64_t>(supply * double(price));
|
||||||
|
|
||||||
|
ret[0] = currencyCode + "/MCAP";
|
||||||
|
|
||||||
|
if (bigChars)
|
||||||
|
{
|
||||||
|
firstIndex = 1;
|
||||||
|
std::string priceString = getCurrencySymbol(currencySymbol) + formatNumberWithSuffix(marketCap, (NUM_SCREENS - 2));
|
||||||
|
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
||||||
|
|
||||||
|
for (std::uint32_t i = firstIndex; i < NUM_SCREENS; i++)
|
||||||
|
{
|
||||||
|
ret[i] = priceString[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string stringValue = std::to_string(marketCap);
|
||||||
|
size_t mcLength = stringValue.length();
|
||||||
|
size_t leadingSpaces = (3 - mcLength % 3) % 3;
|
||||||
|
stringValue = std::string(leadingSpaces, ' ') + stringValue;
|
||||||
|
|
||||||
|
std::uint32_t groups = (mcLength + leadingSpaces) / 3;
|
||||||
|
|
||||||
|
if (groups < NUM_SCREENS)
|
||||||
|
{
|
||||||
|
firstIndex = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = firstIndex; i < NUM_SCREENS - groups - 1; i++)
|
||||||
|
{
|
||||||
|
ret[i] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
ret[NUM_SCREENS - groups - 1] = std::string(" ") + getCurrencySymbol(currencySymbol) + " ";
|
||||||
|
for (std::uint32_t i = 0; i < groups; i++)
|
||||||
|
{
|
||||||
|
ret[(NUM_SCREENS - groups + i)] = stringValue.substr(i * 3, 3).c_str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updated public methods to use the helper methods
|
||||||
|
std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char currencySymbol, bool useSuffixFormat, bool mowMode, bool shareDot)
|
||||||
|
{
|
||||||
|
// For char version, always use the currency symbol
|
||||||
|
return formatPriceData(price, currencySymbol, getCurrencyCode(currencySymbol), useSuffixFormat, mowMode, shareDot, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, const std::string& currencyCode, bool useSuffixFormat, bool mowMode, bool shareDot)
|
||||||
|
{
|
||||||
|
// For string version, let formatPriceData decide whether to use symbol based on if it's a recognized currency
|
||||||
|
char currencyChar = getCurrencyChar(currencyCode);
|
||||||
|
return formatPriceData(price, currencyChar, currencyCode, useSuffixFormat, mowMode, shareDot, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price, char currencySymbol, bool withSatsSymbol)
|
||||||
|
{
|
||||||
|
return formatSatsPerCurrency(price, currencySymbol, getCurrencyCode(currencySymbol), withSatsSymbol, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price, const std::string& currencyCode, bool withSatsSymbol)
|
||||||
|
{
|
||||||
|
return formatSatsPerCurrency(price, getCurrencyChar(currencyCode), currencyCode, withSatsSymbol, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<std::string, NUM_SCREENS> parseBlockHeight(std::uint32_t blockHeight)
|
std::array<std::string, NUM_SCREENS> parseBlockHeight(std::uint32_t blockHeight)
|
||||||
|
@ -273,53 +397,13 @@ std::array<std::string, NUM_SCREENS> parseHalvingCountdown(std::uint32_t blockHe
|
||||||
|
|
||||||
std::array<std::string, NUM_SCREENS> parseMarketCap(std::uint32_t blockHeight, std::uint32_t price, char currencySymbol, bool bigChars)
|
std::array<std::string, NUM_SCREENS> parseMarketCap(std::uint32_t blockHeight, std::uint32_t price, char currencySymbol, bool bigChars)
|
||||||
{
|
{
|
||||||
std::array<std::string, NUM_SCREENS> ret;
|
return formatMarketCap(blockHeight, price, currencySymbol, getCurrencyCode(currencySymbol), bigChars);
|
||||||
std::uint32_t firstIndex = 0;
|
}
|
||||||
double supply = getSupplyAtBlock(blockHeight);
|
|
||||||
uint64_t marketCap = static_cast<std::uint64_t>(supply * double(price));
|
|
||||||
|
|
||||||
ret[0] = getCurrencyCode(currencySymbol) + "/MCAP";
|
std::array<std::string, NUM_SCREENS> parseMarketCap(std::uint32_t blockHeight, std::uint32_t price, const std::string& currencyCode, bool bigChars)
|
||||||
|
{
|
||||||
if (bigChars)
|
char currencyChar = getCurrencyChar(currencyCode);
|
||||||
{
|
return formatMarketCap(blockHeight, price, currencyChar, currencyCode, bigChars);
|
||||||
firstIndex = 1;
|
|
||||||
// Serial.print("Market cap: ");
|
|
||||||
// Serial.println(marketCap);
|
|
||||||
std::string priceString = currencySymbol + formatNumberWithSuffix(marketCap, (NUM_SCREENS - 2));
|
|
||||||
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
|
|
||||||
|
|
||||||
for (std::uint32_t i = firstIndex; i < NUM_SCREENS; i++)
|
|
||||||
{
|
|
||||||
ret[i] = priceString[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::string stringValue = std::to_string(marketCap);
|
|
||||||
size_t mcLength = stringValue.length();
|
|
||||||
size_t leadingSpaces = (3 - mcLength % 3) % 3;
|
|
||||||
stringValue = std::string(leadingSpaces, ' ') + stringValue;
|
|
||||||
|
|
||||||
std::uint32_t groups = (mcLength + leadingSpaces) / 3;
|
|
||||||
|
|
||||||
if (groups < NUM_SCREENS)
|
|
||||||
{
|
|
||||||
firstIndex = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = firstIndex; i < NUM_SCREENS - groups - 1; i++)
|
|
||||||
{
|
|
||||||
ret[i] = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
ret[NUM_SCREENS - groups - 1] = std::string(" ") + currencySymbol + " ";
|
|
||||||
for (std::uint32_t i = 0; i < groups; i++)
|
|
||||||
{
|
|
||||||
ret[(NUM_SCREENS - groups + i)] = stringValue.substr(i * 3, 3).c_str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
|
@ -350,7 +434,12 @@ emscripten::val parseBlockHeightArray(std::uint32_t blockHeight)
|
||||||
|
|
||||||
emscripten::val parsePriceDataArray(std::uint32_t price, const std::string ¤cySymbol, bool useSuffixFormat = false, bool mowMode = false, bool shareDot = false)
|
emscripten::val parsePriceDataArray(std::uint32_t price, const std::string ¤cySymbol, bool useSuffixFormat = false, bool mowMode = false, bool shareDot = false)
|
||||||
{
|
{
|
||||||
return arrayToStringArray(parsePriceData(price, currencySymbol[0], useSuffixFormat, mowMode, shareDot));
|
// Handle both single character and three-character currency codes
|
||||||
|
if (currencySymbol.length() == 1) {
|
||||||
|
return arrayToStringArray(parsePriceData(price, currencySymbol[0], useSuffixFormat, mowMode, shareDot));
|
||||||
|
} else {
|
||||||
|
return arrayToStringArray(parsePriceData(price, currencySymbol, useSuffixFormat, mowMode, shareDot));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emscripten::val parseHalvingCountdownArray(std::uint32_t blockHeight, bool asBlocks)
|
emscripten::val parseHalvingCountdownArray(std::uint32_t blockHeight, bool asBlocks)
|
||||||
|
@ -360,7 +449,12 @@ emscripten::val parseHalvingCountdownArray(std::uint32_t blockHeight, bool asBlo
|
||||||
|
|
||||||
emscripten::val parseMarketCapArray(std::uint32_t blockHeight, std::uint32_t price, const std::string ¤cySymbol, bool bigChars)
|
emscripten::val parseMarketCapArray(std::uint32_t blockHeight, std::uint32_t price, const std::string ¤cySymbol, bool bigChars)
|
||||||
{
|
{
|
||||||
return arrayToStringArray(parseMarketCap(blockHeight, price, currencySymbol[0], bigChars));
|
// Handle both single character and three-character currency codes
|
||||||
|
if (currencySymbol.length() == 1) {
|
||||||
|
return arrayToStringArray(parseMarketCap(blockHeight, price, currencySymbol[0], bigChars));
|
||||||
|
} else {
|
||||||
|
return arrayToStringArray(parseMarketCap(blockHeight, price, currencySymbol, bigChars));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emscripten::val parseBlockFeesArray(std::uint16_t blockFees)
|
emscripten::val parseBlockFeesArray(std::uint16_t blockFees)
|
||||||
|
@ -370,7 +464,12 @@ emscripten::val parseBlockFeesArray(std::uint16_t blockFees)
|
||||||
|
|
||||||
emscripten::val parseSatsPerCurrencyArray(std::uint32_t price, const std::string ¤cySymbol, bool withSatsSymbol)
|
emscripten::val parseSatsPerCurrencyArray(std::uint32_t price, const std::string ¤cySymbol, bool withSatsSymbol)
|
||||||
{
|
{
|
||||||
return arrayToStringArray(parseSatsPerCurrency(price, currencySymbol[0], withSatsSymbol));
|
// Handle both single character and three-character currency codes
|
||||||
|
if (currencySymbol.length() == 1) {
|
||||||
|
return arrayToStringArray(parseSatsPerCurrency(price, currencySymbol[0], withSatsSymbol));
|
||||||
|
} else {
|
||||||
|
return arrayToStringArray(parseSatsPerCurrency(price, currencySymbol, withSatsSymbol));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_BINDINGS(my_module)
|
EMSCRIPTEN_BINDINGS(my_module)
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
|
@ -12,6 +14,41 @@ const char CURRENCY_GBP = ']';
|
||||||
const char CURRENCY_JPY = '^';
|
const char CURRENCY_JPY = '^';
|
||||||
const char CURRENCY_AUD = '_';
|
const char CURRENCY_AUD = '_';
|
||||||
const char CURRENCY_CAD = '`';
|
const char CURRENCY_CAD = '`';
|
||||||
|
const char CURRENCY_ALL = 'L';
|
||||||
|
const char CURRENCY_BWP = 'P';
|
||||||
|
const char CURRENCY_HNL = 'L';
|
||||||
|
const char CURRENCY_HTG = 'G';
|
||||||
|
const char CURRENCY_MWK = 'K';
|
||||||
|
const char CURRENCY_MZN = 'M';
|
||||||
|
const char CURRENCY_NAD = 'N';
|
||||||
|
const char CURRENCY_PYG = 'G';
|
||||||
|
const char CURRENCY_RON = 'L';
|
||||||
|
const char CURRENCY_SZL = 'E';
|
||||||
|
const char CURRENCY_ZAR = 'R';
|
||||||
|
const char CURRENCY_ZMW = 'K';
|
||||||
|
// const char CURRENCY_NZD = '$';
|
||||||
|
// const char CURRENCY_SGD = '$';
|
||||||
|
// const char CURRENCY_HKD = '$';
|
||||||
|
// const char CURRENCY_BND = '$';
|
||||||
|
// const char CURRENCY_FJD = '$';
|
||||||
|
// const char CURRENCY_SBD = '$';
|
||||||
|
// const char CURRENCY_TTD = '$';
|
||||||
|
// const char CURRENCY_XCD = '$';
|
||||||
|
// const char CURRENCY_KYD = '$';
|
||||||
|
// const char CURRENCY_GYD = '$';
|
||||||
|
// const char CURRENCY_BBD = '$';
|
||||||
|
// const char CURRENCY_BSD = '$';
|
||||||
|
// const char CURRENCY_BMD = '$';
|
||||||
|
// const char CURRENCY_LRD = '$';
|
||||||
|
// const char CURRENCY_ZWL = '$';
|
||||||
|
// const char CURRENCY_ARS = '$';
|
||||||
|
// const char CURRENCY_CLP = '$';
|
||||||
|
// const char CURRENCY_COP = '$';
|
||||||
|
// const char CURRENCY_MXN = '$';
|
||||||
|
// const char CURRENCY_UYU = '$';
|
||||||
|
// const char CURRENCY_DOP = '$';
|
||||||
|
// const char CURRENCY_SVC = '$';
|
||||||
|
// const char CURRENCY_SRD = '$';
|
||||||
|
|
||||||
const std::string CURRENCY_CODE_USD = "USD";
|
const std::string CURRENCY_CODE_USD = "USD";
|
||||||
const std::string CURRENCY_CODE_EUR = "EUR";
|
const std::string CURRENCY_CODE_EUR = "EUR";
|
||||||
|
@ -19,14 +56,61 @@ const std::string CURRENCY_CODE_GBP = "GBP";
|
||||||
const std::string CURRENCY_CODE_JPY = "JPY";
|
const std::string CURRENCY_CODE_JPY = "JPY";
|
||||||
const std::string CURRENCY_CODE_AUD = "AUD";
|
const std::string CURRENCY_CODE_AUD = "AUD";
|
||||||
const std::string CURRENCY_CODE_CAD = "CAD";
|
const std::string CURRENCY_CODE_CAD = "CAD";
|
||||||
|
// const std::string CURRENCY_CODE_ALL = "ALL";
|
||||||
|
// const std::string CURRENCY_CODE_BWP = "BWP";
|
||||||
|
// const std::string CURRENCY_CODE_HNL = "HNL";
|
||||||
|
// const std::string CURRENCY_CODE_HTG = "HTG";
|
||||||
|
// const std::string CURRENCY_CODE_MWK = "MWK";
|
||||||
|
// const std::string CURRENCY_CODE_MZN = "MZN";
|
||||||
|
// const std::string CURRENCY_CODE_NAD = "NAD";
|
||||||
|
// const std::string CURRENCY_CODE_PYG = "PYG";
|
||||||
|
// const std::string CURRENCY_CODE_RON = "RON";
|
||||||
|
// const std::string CURRENCY_CODE_SZL = "SZL";
|
||||||
|
// const std::string CURRENCY_CODE_ZAR = "ZAR";
|
||||||
|
// const std::string CURRENCY_CODE_ZMW = "ZMW";
|
||||||
|
// const std::string CURRENCY_CODE_NZD = "NZD";
|
||||||
|
// const std::string CURRENCY_CODE_SGD = "SGD";
|
||||||
|
// const std::string CURRENCY_CODE_HKD = "HKD";
|
||||||
|
// const std::string CURRENCY_CODE_BND = "BND";
|
||||||
|
// const std::string CURRENCY_CODE_FJD = "FJD";
|
||||||
|
// const std::string CURRENCY_CODE_SBD = "SBD";
|
||||||
|
// const std::string CURRENCY_CODE_TTD = "TTD";
|
||||||
|
// const std::string CURRENCY_CODE_XCD = "XCD";
|
||||||
|
// const std::string CURRENCY_CODE_KYD = "KYD";
|
||||||
|
// const std::string CURRENCY_CODE_GYD = "GYD";
|
||||||
|
// const std::string CURRENCY_CODE_BBD = "BBD";
|
||||||
|
// const std::string CURRENCY_CODE_BSD = "BSD";
|
||||||
|
// const std::string CURRENCY_CODE_BMD = "BMD";
|
||||||
|
// const std::string CURRENCY_CODE_LRD = "LRD";
|
||||||
|
// const std::string CURRENCY_CODE_ZWL = "ZWL";
|
||||||
|
// const std::string CURRENCY_CODE_ARS = "ARS";
|
||||||
|
// const std::string CURRENCY_CODE_CLP = "CLP";
|
||||||
|
// const std::string CURRENCY_CODE_COP = "COP";
|
||||||
|
// const std::string CURRENCY_CODE_MXN = "MXN";
|
||||||
|
// const std::string CURRENCY_CODE_UYU = "UYU";
|
||||||
|
// const std::string CURRENCY_CODE_DOP = "DOP";
|
||||||
|
// const std::string CURRENCY_CODE_SVC = "SVC";
|
||||||
|
// const std::string CURRENCY_CODE_SRD = "SRD";
|
||||||
|
const std::string CURRENCY_CODE_UNKNOWN = " ";
|
||||||
|
|
||||||
|
// Public methods
|
||||||
std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char currency, bool useSuffixFormat = false, bool mowMode = false, bool shareDot = false);
|
std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char currency, bool useSuffixFormat = false, bool mowMode = false, bool shareDot = false);
|
||||||
|
std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, const std::string& currencyCode, bool useSuffixFormat = false, bool mowMode = false, bool shareDot = false);
|
||||||
std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price, char currencySymbol, bool withSatsSymbol);
|
std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price, char currencySymbol, bool withSatsSymbol);
|
||||||
|
std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price, const std::string& currencyCode, bool withSatsSymbol);
|
||||||
std::array<std::string, NUM_SCREENS> parseBlockHeight(std::uint32_t blockHeight);
|
std::array<std::string, NUM_SCREENS> parseBlockHeight(std::uint32_t blockHeight);
|
||||||
std::array<std::string, NUM_SCREENS> parseHalvingCountdown(std::uint32_t blockHeight, bool asBlocks);
|
std::array<std::string, NUM_SCREENS> parseHalvingCountdown(std::uint32_t blockHeight, bool asBlocks);
|
||||||
std::array<std::string, NUM_SCREENS> parseMarketCap(std::uint32_t blockHeight, std::uint32_t price, char currencySymbol, bool bigChars);
|
std::array<std::string, NUM_SCREENS> parseMarketCap(std::uint32_t blockHeight, std::uint32_t price, char currencySymbol, bool bigChars);
|
||||||
|
std::array<std::string, NUM_SCREENS> parseMarketCap(std::uint32_t blockHeight, std::uint32_t price, const std::string& currencyCode, bool bigChars);
|
||||||
std::array<std::string, NUM_SCREENS> parseBlockFees(std::uint16_t blockFees);
|
std::array<std::string, NUM_SCREENS> parseBlockFees(std::uint16_t blockFees);
|
||||||
|
|
||||||
char getCurrencySymbol(char input);
|
char getCurrencySymbol(char input);
|
||||||
std::string getCurrencyCode(char input);
|
std::string getCurrencyCode(char input);
|
||||||
char getCurrencyChar(const std::string& input);
|
char getCurrencyChar(const std::string& input);
|
||||||
|
|
||||||
|
// Private helper methods
|
||||||
|
namespace {
|
||||||
|
std::array<std::string, NUM_SCREENS> formatPriceData(std::uint32_t price, char currencySymbol, const std::string& currencyCode, bool useSuffixFormat, bool mowMode, bool shareDot, bool useSymbol = true);
|
||||||
|
std::array<std::string, NUM_SCREENS> formatSatsPerCurrency(std::uint32_t price, char currencySymbol, const std::string& currencyCode, bool withSatsSymbol, bool alwaysShowSats = false);
|
||||||
|
std::array<std::string, NUM_SCREENS> formatMarketCap(std::uint32_t blockHeight, std::uint32_t price, char currencySymbol, const std::string& currencyCode, bool bigChars);
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "led_handler.hpp"
|
#include "led_handler.hpp"
|
||||||
|
#include "lnbits.hpp"
|
||||||
|
|
||||||
#define MAX_ATTEMPTS_WIFI_CONNECTION 20
|
#define MAX_ATTEMPTS_WIFI_CONNECTION 20
|
||||||
|
|
||||||
|
@ -393,6 +394,10 @@ void setupWebsocketClients(void *pvParameters)
|
||||||
{
|
{
|
||||||
DataSourceType dataSource = getDataSource();
|
DataSourceType dataSource = getDataSource();
|
||||||
|
|
||||||
|
if (preferences.getBool("lnbitsEnabled", DEFAULT_LNBITS_ENABLED)) {
|
||||||
|
setupLnbits();
|
||||||
|
}
|
||||||
|
|
||||||
if (dataSource == BTCLOCK_SOURCE || dataSource == CUSTOM_SOURCE)
|
if (dataSource == BTCLOCK_SOURCE || dataSource == CUSTOM_SOURCE)
|
||||||
{
|
{
|
||||||
V2Notify::setupV2Notify();
|
V2Notify::setupV2Notify();
|
||||||
|
|
|
@ -100,3 +100,7 @@ enum DataSourceType {
|
||||||
#ifndef DEFAULT_BOOT_TEXT
|
#ifndef DEFAULT_BOOT_TEXT
|
||||||
#define DEFAULT_BOOT_TEXT "BTCLOCK"
|
#define DEFAULT_BOOT_TEXT "BTCLOCK"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define DEFAULT_LNBITS_INSTANCE "demo.lnbits.com"
|
||||||
|
#define DEFAULT_LNBITS_HTTPS true
|
||||||
|
#define DEFAULT_LNBITS_ENABLED false
|
||||||
|
|
151
src/lib/lnbits.cpp
Normal file
151
src/lib/lnbits.cpp
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
#include "lnbits.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
|
|
||||||
|
LNBitsFetch* LNBitsFetch::instance = nullptr;
|
||||||
|
|
||||||
|
LNBitsFetch::LNBitsFetch() : initialized(false), taskHandle(nullptr) {}
|
||||||
|
|
||||||
|
LNBitsFetch& LNBitsFetch::getInstance() {
|
||||||
|
if (instance == nullptr) {
|
||||||
|
instance = new LNBitsFetch();
|
||||||
|
}
|
||||||
|
return *instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LNBitsFetch::setup() {
|
||||||
|
if (initialized) return;
|
||||||
|
|
||||||
|
currentCurrency = getActiveCurrencies().front();
|
||||||
|
|
||||||
|
xTaskCreate(taskLNBits, "lnbitsTask", 6 * 1024, NULL, tskIDLE_PRIORITY, &taskHandle);
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
// Fetch rates immediately when setup
|
||||||
|
fetchRates();
|
||||||
|
}
|
||||||
|
|
||||||
|
String LNBitsFetch::buildApiUrl(const std::string& currency) {
|
||||||
|
String instance = preferences.getString("lnbitsInstance", DEFAULT_LNBITS_INSTANCE);
|
||||||
|
bool useHttps = preferences.getBool("lnbitsHttps", DEFAULT_LNBITS_HTTPS);
|
||||||
|
|
||||||
|
String protocol = useHttps ? "https" : "http";
|
||||||
|
return protocol + "://" + instance + "/api/v1/rate/" + String(currency.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LNBitsFetch::fetchRates() {
|
||||||
|
if (!initialized) return;
|
||||||
|
|
||||||
|
std::vector<std::string> currencies = getActiveCurrencies();
|
||||||
|
HTTPClient http;
|
||||||
|
|
||||||
|
for (const std::string& currency : currencies) {
|
||||||
|
String apiUrl = buildApiUrl(currency);
|
||||||
|
|
||||||
|
if (debugLogEnabled()) {
|
||||||
|
Serial.printf("Fetching LNBits rate for %s from %s\n", currency.c_str(), apiUrl.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
http.begin(apiUrl);
|
||||||
|
int httpCode = http.GET();
|
||||||
|
|
||||||
|
if (httpCode == HTTP_CODE_OK) {
|
||||||
|
String payload = http.getString();
|
||||||
|
JsonDocument doc;
|
||||||
|
DeserializationError error = deserializeJson(doc, payload);
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
if (doc.containsKey("price")) {
|
||||||
|
uint price = doc["price"].as<uint>();
|
||||||
|
|
||||||
|
if (price > 0) {
|
||||||
|
priceMap[currency] = price;
|
||||||
|
unsigned long int currentTime = esp_timer_get_time() / 1000000;
|
||||||
|
lastUpdateMap[currency] = currentTime;
|
||||||
|
|
||||||
|
if (debugLogEnabled()) {
|
||||||
|
Serial.printf("Updated LNBits price for %s: %d\n", currency.c_str(), price);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the screen if it's currently displaying price-related information
|
||||||
|
if (workQueue != nullptr && (
|
||||||
|
ScreenHandler::getCurrentScreen() == SCREEN_BTC_TICKER ||
|
||||||
|
ScreenHandler::getCurrentScreen() == SCREEN_SATS_PER_CURRENCY ||
|
||||||
|
ScreenHandler::getCurrentScreen() == SCREEN_MARKET_CAP)) {
|
||||||
|
WorkItem rateUpdate = {TASK_PRICE_UPDATE, currency[0]};
|
||||||
|
xQueueSend(workQueue, &rateUpdate, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (debugLogEnabled()) {
|
||||||
|
Serial.printf("JSON parse error for %s: %s\n", currency.c_str(), error.c_str());
|
||||||
|
}
|
||||||
|
} else if (debugLogEnabled()) {
|
||||||
|
Serial.printf("HTTP error for %s: %d\n", currency.c_str(), httpCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
http.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LNBitsFetch::stop() {
|
||||||
|
if (taskHandle != nullptr) {
|
||||||
|
vTaskDelete(taskHandle);
|
||||||
|
taskHandle = nullptr;
|
||||||
|
}
|
||||||
|
initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LNBitsFetch::restart() {
|
||||||
|
stop();
|
||||||
|
setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LNBitsFetch::isInitialized() const {
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskHandle_t LNBitsFetch::getTaskHandle() const {
|
||||||
|
return taskHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint LNBitsFetch::getPrice(const std::string& currencyCode) {
|
||||||
|
if (priceMap.find(currencyCode) == priceMap.end()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return priceMap[currencyCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
void LNBitsFetch::setPrice(uint newPrice, const std::string& currencyCode) {
|
||||||
|
priceMap[currencyCode] = newPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long int LNBitsFetch::getLastPriceUpdate(const std::string& currencyCode) {
|
||||||
|
if (lastUpdateMap.find(currencyCode) == lastUpdateMap.end()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return lastUpdateMap[currencyCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupLnbits() {
|
||||||
|
if (preferences.getBool("lnbitsEnabled", DEFAULT_LNBITS_ENABLED)) {
|
||||||
|
LNBitsFetch::getInstance().setup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void taskLNBits(void* pvParameters) {
|
||||||
|
for (;;) {
|
||||||
|
// Wait for notification from timer
|
||||||
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
|
||||||
|
// Fetch rates
|
||||||
|
LNBitsFetch::getInstance().fetchRates();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LNBitsFetch::setCurrentCurrency(const std::string& currency) {
|
||||||
|
currentCurrency = currency;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LNBitsFetch::getCurrentCurrency() const {
|
||||||
|
return currentCurrency;
|
||||||
|
}
|
43
src/lib/lnbits.hpp
Normal file
43
src/lib/lnbits.hpp
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <HTTPClient.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "lib/screen_handler.hpp"
|
||||||
|
|
||||||
|
class LNBitsFetch {
|
||||||
|
private:
|
||||||
|
LNBitsFetch();
|
||||||
|
static LNBitsFetch* instance;
|
||||||
|
|
||||||
|
bool initialized;
|
||||||
|
TaskHandle_t taskHandle;
|
||||||
|
std::map<std::string, uint> priceMap;
|
||||||
|
std::map<std::string, unsigned long int> lastUpdateMap;
|
||||||
|
std::string currentCurrency;
|
||||||
|
String buildApiUrl(const std::string& currency);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static LNBitsFetch& getInstance();
|
||||||
|
|
||||||
|
void setup();
|
||||||
|
void fetchRates();
|
||||||
|
void stop();
|
||||||
|
void restart();
|
||||||
|
void setCurrentCurrency(const std::string& currency);
|
||||||
|
std::string getCurrentCurrency() const;
|
||||||
|
|
||||||
|
bool isInitialized() const;
|
||||||
|
TaskHandle_t getTaskHandle() const;
|
||||||
|
|
||||||
|
uint getPrice(const std::string& currencyCode);
|
||||||
|
void setPrice(uint newPrice, const std::string& currencyCode);
|
||||||
|
unsigned long int getLastPriceUpdate(const std::string& currencyCode);
|
||||||
|
};
|
||||||
|
|
||||||
|
void setupLnbits();
|
||||||
|
void taskLNBits(void* pvParameters);
|
|
@ -89,24 +89,47 @@ bool ScreenHandler::handleCurrencyRotation(bool forward) {
|
||||||
std::vector<std::string> ac = getActiveCurrencies();
|
std::vector<std::string> ac = getActiveCurrencies();
|
||||||
if (ac.empty()) return false;
|
if (ac.empty()) return false;
|
||||||
|
|
||||||
std::string curCode = getCurrencyCode(getCurrentCurrency());
|
if (preferences.getBool("lnbitsEnabled", DEFAULT_LNBITS_ENABLED)) {
|
||||||
auto it = std::find(ac.begin(), ac.end(), curCode);
|
std::string curCode = LNBitsFetch::getInstance().getCurrentCurrency();
|
||||||
|
auto it = std::find(ac.begin(), ac.end(), curCode);
|
||||||
|
|
||||||
if (it == ac.end()) {
|
if (it == ac.end()) {
|
||||||
// Current currency not found in active currencies - initialize based on direction
|
// Current currency not found in active currencies - initialize based on direction
|
||||||
setCurrentCurrency(getCurrencyChar(forward ? ac.front() : ac.back()));
|
LNBitsFetch::getInstance().setCurrentCurrency(forward ? ac.front() : ac.back());
|
||||||
setCurrentScreen(getCurrentScreen());
|
setCurrentScreen(getCurrentScreen());
|
||||||
return true;
|
return true;
|
||||||
} else if (forward && curCode != ac.back()) {
|
} else if (forward && curCode != ac.back()) {
|
||||||
// Moving forward and not at last currency
|
// Moving forward and not at last currency
|
||||||
setCurrentCurrency(getCurrencyChar(ac.at(std::distance(ac.begin(), it) + 1)));
|
LNBitsFetch::getInstance().setCurrentCurrency(ac.at(std::distance(ac.begin(), it) + 1));
|
||||||
setCurrentScreen(getCurrentScreen());
|
setCurrentScreen(getCurrentScreen());
|
||||||
return true;
|
return true;
|
||||||
} else if (!forward && curCode != ac.front()) {
|
} else if (!forward && curCode != ac.front()) {
|
||||||
// Moving backward and not at first currency
|
// Moving backward and not at first currency
|
||||||
setCurrentCurrency(getCurrencyChar(ac.at(std::distance(ac.begin(), it) - 1)));
|
LNBitsFetch::getInstance().setCurrentCurrency(ac.at(std::distance(ac.begin(), it) - 1));
|
||||||
setCurrentScreen(getCurrentScreen());
|
setCurrentScreen(getCurrentScreen());
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
std::string curCode = getCurrencyCode(getCurrentCurrency());
|
||||||
|
auto it = std::find(ac.begin(), ac.end(), curCode);
|
||||||
|
|
||||||
|
if (it == ac.end()) {
|
||||||
|
// Current currency not found in active currencies - initialize based on direction
|
||||||
|
setCurrentCurrency(getCurrencyChar(forward ? ac.front() : ac.back()));
|
||||||
|
setCurrentScreen(getCurrentScreen());
|
||||||
|
return true;
|
||||||
|
} else if (forward && curCode != ac.back()) {
|
||||||
|
// Moving forward and not at last currency
|
||||||
|
setCurrentCurrency(getCurrencyChar(ac.at(std::distance(ac.begin(), it) + 1)));
|
||||||
|
setCurrentScreen(getCurrentScreen());
|
||||||
|
return true;
|
||||||
|
} else if (!forward && curCode != ac.front()) {
|
||||||
|
// Moving backward and not at first currency
|
||||||
|
setCurrentCurrency(getCurrencyChar(ac.at(std::distance(ac.begin(), it) - 1)));
|
||||||
|
setCurrentScreen(getCurrentScreen());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// If we're at the last/first currency of current screen, let nextScreen/previousScreen handle it
|
// If we're at the last/first currency of current screen, let nextScreen/previousScreen handle it
|
||||||
return false;
|
return false;
|
||||||
|
@ -241,18 +264,39 @@ void workerTask(void *pvParameters) {
|
||||||
|
|
||||||
case TASK_PRICE_UPDATE: {
|
case TASK_PRICE_UPDATE: {
|
||||||
uint currency = ScreenHandler::getCurrentCurrency();
|
uint currency = ScreenHandler::getCurrentCurrency();
|
||||||
uint price = getPrice(currency);
|
|
||||||
|
uint price;
|
||||||
|
if (preferences.getBool("lnbitsEnabled", DEFAULT_LNBITS_ENABLED)) {
|
||||||
|
price = LNBitsFetch::getInstance().getPrice(LNBitsFetch::getInstance().getCurrentCurrency());
|
||||||
|
} else {
|
||||||
|
price = getPrice(currency);
|
||||||
|
}
|
||||||
|
|
||||||
if (currentScreenValue == SCREEN_BTC_TICKER) {
|
if (currentScreenValue == SCREEN_BTC_TICKER) {
|
||||||
taskEpdContent = parsePriceData(price, currency, preferences.getBool("suffixPrice", DEFAULT_SUFFIX_PRICE),
|
if (preferences.getBool("lnbitsEnabled", DEFAULT_LNBITS_ENABLED)) {
|
||||||
preferences.getBool("mowMode", DEFAULT_MOW_MODE),
|
taskEpdContent = parsePriceData(price, LNBitsFetch::getInstance().getCurrentCurrency(), preferences.getBool("suffixPrice", DEFAULT_SUFFIX_PRICE),
|
||||||
preferences.getBool("suffixShareDot", DEFAULT_SUFFIX_SHARE_DOT)
|
preferences.getBool("mowMode", DEFAULT_MOW_MODE),
|
||||||
);
|
preferences.getBool("suffixShareDot", DEFAULT_SUFFIX_SHARE_DOT)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
taskEpdContent = parsePriceData(price, currency, preferences.getBool("suffixPrice", DEFAULT_SUFFIX_PRICE),
|
||||||
|
preferences.getBool("mowMode", DEFAULT_MOW_MODE),
|
||||||
|
preferences.getBool("suffixShareDot", DEFAULT_SUFFIX_SHARE_DOT)
|
||||||
|
);
|
||||||
|
}
|
||||||
} else if (currentScreenValue == SCREEN_SATS_PER_CURRENCY) {
|
} else if (currentScreenValue == SCREEN_SATS_PER_CURRENCY) {
|
||||||
taskEpdContent = parseSatsPerCurrency(price, currency, preferences.getBool("useSatsSymbol", DEFAULT_USE_SATS_SYMBOL));
|
if (preferences.getBool("lnbitsEnabled", DEFAULT_LNBITS_ENABLED)) {
|
||||||
|
taskEpdContent = parseSatsPerCurrency(price, LNBitsFetch::getInstance().getCurrentCurrency(), preferences.getBool("useSatsSymbol", DEFAULT_USE_SATS_SYMBOL));
|
||||||
|
} else {
|
||||||
|
taskEpdContent = parseSatsPerCurrency(price, currency, preferences.getBool("useSatsSymbol", DEFAULT_USE_SATS_SYMBOL));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
auto& blockNotify = BlockNotify::getInstance();
|
auto& blockNotify = BlockNotify::getInstance();
|
||||||
taskEpdContent = parseMarketCap(blockNotify.getBlockHeight(), price, currency, preferences.getBool("mcapBigChar", DEFAULT_MCAP_BIG_CHAR));
|
if (preferences.getBool("lnbitsEnabled", DEFAULT_LNBITS_ENABLED)) {
|
||||||
|
taskEpdContent = parseMarketCap(blockNotify.getBlockHeight(), price, LNBitsFetch::getInstance().getCurrentCurrency(), preferences.getBool("mcapBigChar", DEFAULT_MCAP_BIG_CHAR));
|
||||||
|
} else {
|
||||||
|
taskEpdContent = parseMarketCap(blockNotify.getBlockHeight(), price, currency, preferences.getBool("mcapBigChar", DEFAULT_MCAP_BIG_CHAR));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EPDManager::getInstance().setContent(taskEpdContent);
|
EPDManager::getInstance().setContent(taskEpdContent);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "timers.hpp"
|
#include "timers.hpp"
|
||||||
#include "led_handler.hpp"
|
#include "led_handler.hpp"
|
||||||
|
#include "lnbits.hpp"
|
||||||
|
|
||||||
esp_timer_handle_t screenRotateTimer;
|
esp_timer_handle_t screenRotateTimer;
|
||||||
esp_timer_handle_t minuteTimer;
|
esp_timer_handle_t minuteTimer;
|
||||||
|
@ -79,6 +80,11 @@ void IRAM_ATTR minuteTimerISR(void *arg) {
|
||||||
vTaskNotifyGiveFromISR(miningPoolHandle, &xHigherPriorityTaskWoken);
|
vTaskNotifyGiveFromISR(miningPoolHandle, &xHigherPriorityTaskWoken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TaskHandle_t lnbitsHandle = LNBitsFetch::getInstance().getTaskHandle();
|
||||||
|
if (lnbitsHandle != NULL) {
|
||||||
|
vTaskNotifyGiveFromISR(lnbitsHandle, &xHigherPriorityTaskWoken);
|
||||||
|
}
|
||||||
|
|
||||||
if (xHigherPriorityTaskWoken == pdTRUE) {
|
if (xHigherPriorityTaskWoken == pdTRUE) {
|
||||||
portYIELD_FROM_ISR();
|
portYIELD_FROM_ISR();
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,21 +77,22 @@ namespace V2Notify
|
||||||
|
|
||||||
buffer = new uint8_t[responseLength];
|
buffer = new uint8_t[responseLength];
|
||||||
|
|
||||||
response["type"] = "subscribe";
|
if (!preferences.getBool("lnbitsEnabled", DEFAULT_LNBITS_ENABLED)) {
|
||||||
response["eventType"] = "price";
|
response["type"] = "subscribe";
|
||||||
|
response["eventType"] = "price";
|
||||||
|
|
||||||
JsonArray currenciesArray = response["currencies"].to<JsonArray>();
|
JsonArray currenciesArray = response["currencies"].to<JsonArray>();
|
||||||
|
|
||||||
for (const auto &str : getActiveCurrencies())
|
for (const auto &str : getActiveCurrencies())
|
||||||
{
|
{
|
||||||
currenciesArray.add(str);
|
currenciesArray.add(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
responseLength = measureMsgPack(response);
|
||||||
|
buffer = new uint8_t[responseLength];
|
||||||
|
serializeMsgPack(response, buffer, responseLength);
|
||||||
|
webSocket.sendBIN(buffer, responseLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
// response["currencies"] = currenciesArray;
|
|
||||||
responseLength = measureMsgPack(response);
|
|
||||||
buffer = new uint8_t[responseLength];
|
|
||||||
serializeMsgPack(response, buffer, responseLength);
|
|
||||||
webSocket.sendBIN(buffer, responseLength);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WStype_TEXT:
|
case WStype_TEXT:
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
static const char* JSON_CONTENT = "application/json";
|
static const char* JSON_CONTENT = "application/json";
|
||||||
|
|
||||||
static const char *const PROGMEM strSettings[] = {
|
static const char *const PROGMEM strSettings[] = {
|
||||||
"hostnamePrefix", "mempoolInstance", "nostrPubKey", "nostrRelay", "bitaxeHostname", "miningPoolName", "miningPoolUser", "nostrZapPubkey", "httpAuthUser", "httpAuthPass", "gitReleaseUrl", "poolLogosUrl", "ceEndpoint", "fontName", "localPoolEndpoint", "tzString"};
|
"hostnamePrefix", "mempoolInstance", "nostrPubKey", "nostrRelay", "bitaxeHostname", "miningPoolName", "miningPoolUser", "nostrZapPubkey", "httpAuthUser", "httpAuthPass", "gitReleaseUrl", "poolLogosUrl", "ceEndpoint", "fontName", "localPoolEndpoint", "tzString", "lnbitsInstance"};
|
||||||
|
|
||||||
static const char *const PROGMEM uintSettings[] = {"minSecPriceUpd", "fullRefreshMin", "ledBrightness", "flMaxBrightness", "flEffectDelay", "luxLightToggle", "wpTimeout"};
|
static const char *const PROGMEM uintSettings[] = {"minSecPriceUpd", "fullRefreshMin", "ledBrightness", "flMaxBrightness", "flEffectDelay", "luxLightToggle", "wpTimeout"};
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ static const char *const PROGMEM boolSettings[] = {"ledTestOnPower", "ledFlashOn
|
||||||
"mempoolSecure", "bitaxeEnabled",
|
"mempoolSecure", "bitaxeEnabled",
|
||||||
"miningPoolStats", "verticalDesc",
|
"miningPoolStats", "verticalDesc",
|
||||||
"nostrZapNotify", "httpAuthEnabled",
|
"nostrZapNotify", "httpAuthEnabled",
|
||||||
"enableDebugLog", "ceDisableSSL", "dndEnabled", "dndTimeBasedEnabled"};
|
"enableDebugLog", "ceDisableSSL", "dndEnabled", "dndTimeBasedEnabled", "lnbitsEnabled", "lnbitsHttps"};
|
||||||
|
|
||||||
AsyncWebServer server(80);
|
AsyncWebServer server(80);
|
||||||
AsyncEventSource events("/events");
|
AsyncEventSource events("/events");
|
||||||
|
@ -252,9 +252,15 @@ JsonDocument getStatusObject()
|
||||||
conStatus["blocks"] = blockNotify.isConnected();
|
conStatus["blocks"] = blockNotify.isConnected();
|
||||||
conStatus["V2"] = V2Notify::isV2NotifyConnected();
|
conStatus["V2"] = V2Notify::isV2NotifyConnected();
|
||||||
conStatus["nostr"] = nostrConnected();
|
conStatus["nostr"] = nostrConnected();
|
||||||
|
conStatus["lnbits"] = LNBitsFetch::getInstance().isInitialized();
|
||||||
|
|
||||||
root["rssi"] = WiFi.RSSI();
|
root["rssi"] = WiFi.RSSI();
|
||||||
root["currency"] = getCurrencyCode(ScreenHandler::getCurrentCurrency());
|
|
||||||
|
if (preferences.getBool("lnbitsEnabled", DEFAULT_LNBITS_ENABLED)) {
|
||||||
|
root["currency"] = LNBitsFetch::getInstance().getCurrentCurrency();
|
||||||
|
} else {
|
||||||
|
root["currency"] = getCurrencyCode(ScreenHandler::getCurrentCurrency());
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAS_FRONTLIGHT
|
#ifdef HAS_FRONTLIGHT
|
||||||
std::vector<uint16_t> statuses = ledHandler.frontlightGetStatus();
|
std::vector<uint16_t> statuses = ledHandler.frontlightGetStatus();
|
||||||
|
@ -713,6 +719,12 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
|
||||||
root["ledFlashOnZap"] = preferences.getBool("ledFlashOnZap", DEFAULT_LED_FLASH_ON_ZAP);
|
root["ledFlashOnZap"] = preferences.getBool("ledFlashOnZap", DEFAULT_LED_FLASH_ON_ZAP);
|
||||||
root["fontName"] = preferences.getString("fontName", DEFAULT_FONT_NAME);
|
root["fontName"] = preferences.getString("fontName", DEFAULT_FONT_NAME);
|
||||||
root["availableFonts"] = FontNames::getAvailableFonts();
|
root["availableFonts"] = FontNames::getAvailableFonts();
|
||||||
|
|
||||||
|
// LNBits settings
|
||||||
|
root["lnbitsEnabled"] = preferences.getBool("lnbitsEnabled", DEFAULT_LNBITS_ENABLED);
|
||||||
|
root["lnbitsInstance"] = preferences.getString("lnbitsInstance", DEFAULT_LNBITS_INSTANCE);
|
||||||
|
root["lnbitsHttps"] = preferences.getBool("lnbitsHttps", DEFAULT_LNBITS_HTTPS);
|
||||||
|
|
||||||
// Custom endpoint settings (only used for CUSTOM_SOURCE)
|
// Custom endpoint settings (only used for CUSTOM_SOURCE)
|
||||||
root["customEndpoint"] = preferences.getString("customEndpoint", DEFAULT_CUSTOM_ENDPOINT);
|
root["customEndpoint"] = preferences.getString("customEndpoint", DEFAULT_CUSTOM_ENDPOINT);
|
||||||
root["customEndpointDisableSSL"] = preferences.getBool("customEndpointDisableSSL", DEFAULT_CUSTOM_ENDPOINT_DISABLE_SSL);
|
root["customEndpointDisableSSL"] = preferences.getBool("customEndpointDisableSSL", DEFAULT_CUSTOM_ENDPOINT_DISABLE_SSL);
|
||||||
|
@ -917,6 +929,7 @@ void onApiStopDataSources(AsyncWebServerRequest *request)
|
||||||
|
|
||||||
stopPriceNotify();
|
stopPriceNotify();
|
||||||
BlockNotify::getInstance().stop();
|
BlockNotify::getInstance().stop();
|
||||||
|
LNBitsFetch::getInstance().stop();
|
||||||
|
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
@ -928,6 +941,9 @@ void onApiRestartDataSources(AsyncWebServerRequest *request)
|
||||||
|
|
||||||
restartPriceNotify();
|
restartPriceNotify();
|
||||||
BlockNotify::getInstance().restart();
|
BlockNotify::getInstance().restart();
|
||||||
|
if (preferences.getBool("lnbitsEnabled", DEFAULT_LNBITS_ENABLED)) {
|
||||||
|
LNBitsFetch::getInstance().restart();
|
||||||
|
}
|
||||||
|
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
@ -1077,10 +1093,17 @@ void onApiShowCurrency(AsyncWebServerRequest *request)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char curChar = getCurrencyChar(currency);
|
// LNbits: set currency using a string
|
||||||
|
if (preferences.getBool("lnbitsEnabled", DEFAULT_LNBITS_ENABLED)) {
|
||||||
|
LNBitsFetch::getInstance().setCurrentCurrency(currency);
|
||||||
|
ScreenHandler::setCurrentScreen(ScreenHandler::getCurrentScreen());
|
||||||
|
|
||||||
ScreenHandler::setCurrentCurrency(curChar);
|
} else {
|
||||||
ScreenHandler::setCurrentScreen(ScreenHandler::getCurrentScreen());
|
// Normal situation: set currency using a char
|
||||||
|
char curChar = getCurrencyChar(currency);
|
||||||
|
ScreenHandler::setCurrentCurrency(curChar);
|
||||||
|
ScreenHandler::setCurrentScreen(ScreenHandler::getCurrentScreen());
|
||||||
|
}
|
||||||
|
|
||||||
request->send(HTTP_OK);
|
request->send(HTTP_OK);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -8,6 +8,11 @@
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
#include "AsyncJson.h"
|
#include "AsyncJson.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <AsyncTCP.h>
|
||||||
|
#include <ESPmDNS.h>
|
||||||
|
#include <Update.h>
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "lib/block_notify.hpp"
|
#include "lib/block_notify.hpp"
|
||||||
#include "lib/led_handler.hpp"
|
#include "lib/led_handler.hpp"
|
||||||
|
@ -15,6 +20,11 @@
|
||||||
#include "lib/screen_handler.hpp"
|
#include "lib/screen_handler.hpp"
|
||||||
#include "webserver/OneParamRewrite.hpp"
|
#include "webserver/OneParamRewrite.hpp"
|
||||||
#include "lib/mining_pool/pool_factory.hpp"
|
#include "lib/mining_pool/pool_factory.hpp"
|
||||||
|
#include "lib/lnbits.hpp"
|
||||||
|
#include "lib/v2_notify.hpp"
|
||||||
|
#include "lib/ota.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
|
|
||||||
|
|
||||||
extern TaskHandle_t eventSourceTaskHandle;
|
extern TaskHandle_t eventSourceTaskHandle;
|
||||||
|
|
||||||
|
|
|
@ -36,12 +36,15 @@ void test_CorrectSatsPerDollarConversion(void)
|
||||||
void test_SatsPerDollarAfter1B(void)
|
void test_SatsPerDollarAfter1B(void)
|
||||||
{
|
{
|
||||||
std::array<std::string, NUM_SCREENS> output = parseSatsPerCurrency(120000000, CURRENCY_USD, false);
|
std::array<std::string, NUM_SCREENS> output = parseSatsPerCurrency(120000000, CURRENCY_USD, false);
|
||||||
TEST_ASSERT_EQUAL_STRING("SATS/USD", output[0].c_str());
|
|
||||||
TEST_ASSERT_EQUAL_STRING("0", output[NUM_SCREENS - 5].c_str());
|
std::string joined = joinArrayWithBrackets(output);
|
||||||
TEST_ASSERT_EQUAL_STRING(".", output[NUM_SCREENS - 4].c_str());
|
|
||||||
TEST_ASSERT_EQUAL_STRING("8", output[NUM_SCREENS - 3].c_str());
|
TEST_ASSERT_EQUAL_STRING_MESSAGE("SATS/USD", output[0].c_str(), joined.c_str());
|
||||||
TEST_ASSERT_EQUAL_STRING("3", output[NUM_SCREENS - 2].c_str());
|
TEST_ASSERT_EQUAL_STRING_MESSAGE("0", output[NUM_SCREENS - 5].c_str(), joined.c_str());
|
||||||
TEST_ASSERT_EQUAL_STRING("3", output[NUM_SCREENS - 1].c_str());
|
TEST_ASSERT_EQUAL_STRING_MESSAGE(".", output[NUM_SCREENS - 4].c_str(), joined.c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE("8", output[NUM_SCREENS - 3].c_str(), joined.c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE("3", output[NUM_SCREENS - 2].c_str(), joined.c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE("3", output[NUM_SCREENS - 1].c_str(), joined.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_CorrectSatsPerPoundConversion(void)
|
void test_CorrectSatsPerPoundConversion(void)
|
||||||
|
@ -272,6 +275,24 @@ void test_Mcap1TrillionJpySmallChars(void)
|
||||||
TEST_ASSERT_EQUAL_STRING("000", output[NUM_SCREENS - 1].c_str());
|
TEST_ASSERT_EQUAL_STRING("000", output[NUM_SCREENS - 1].c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_PriceDataWithCurrencyCode(void)
|
||||||
|
{
|
||||||
|
std::array<std::string, NUM_SCREENS> output = parsePriceData(10000, "PYG", false, false, false);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("BTC/PYG", output[0].c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_SatsPerCurrencyWithCurrencyCode(void)
|
||||||
|
{
|
||||||
|
std::array<std::string, NUM_SCREENS> output = parseSatsPerCurrency(100000, "ZAR", false);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("SATS/ZAR", output[0].c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_McapWithCurrencyCode(void)
|
||||||
|
{
|
||||||
|
std::array<std::string, NUM_SCREENS> output = parseMarketCap(100000, 10000, "PYG", true);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("PYG/MCAP", output[0].c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// not needed when using generate_test_runner.rb
|
// not needed when using generate_test_runner.rb
|
||||||
int runUnityTests(void)
|
int runUnityTests(void)
|
||||||
{
|
{
|
||||||
|
@ -295,6 +316,9 @@ int runUnityTests(void)
|
||||||
RUN_TEST(test_PriceSuffixModeCompact2);
|
RUN_TEST(test_PriceSuffixModeCompact2);
|
||||||
RUN_TEST(test_PriceSuffixModeMow);
|
RUN_TEST(test_PriceSuffixModeMow);
|
||||||
RUN_TEST(test_PriceSuffixModeMowCompact);
|
RUN_TEST(test_PriceSuffixModeMowCompact);
|
||||||
|
RUN_TEST(test_PriceDataWithCurrencyCode);
|
||||||
|
RUN_TEST(test_SatsPerCurrencyWithCurrencyCode);
|
||||||
|
RUN_TEST(test_McapWithCurrencyCode);
|
||||||
|
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue