ESP32: добавить баланс и экран ключей
This commit is contained in:
parent
f095182673
commit
9e6ff07136
@ -3,7 +3,7 @@
|
|||||||
- Краткое описание: минимальный UI-прототип для сабсервера на базе `LVGL + subserver touch`, с Wi-Fi flow, серверными адресами и общим экраном редактирования текста.
|
- Краткое описание: минимальный UI-прототип для сабсервера на базе `LVGL + subserver touch`, с Wi-Fi flow, серверными адресами и общим экраном редактирования текста.
|
||||||
- Что проверять:
|
- Что проверять:
|
||||||
- стартует экран `HOME`;
|
- стартует экран `HOME`;
|
||||||
- на `HOME` видны реальное значение сабсервера или `subserver not set`, реальное значение логина или `login not set`, при отсутствии секрета строка `secret not set`, а также `STATUS`, верхний правый блок с процентом батареи, иконкой батареи и индикатором Wi-Fi, кнопка `SETTINGS` и нижняя подпись `SHiNE subserver (v.0.18)`;
|
- на `HOME` видны реальное значение сабсервера или `subserver not set`, реальное значение логина или `login not set`, при отсутствии секрета строка `secret not set`, а также `STATUS`, верхний правый блок с процентом батареи, иконкой батареи и индикатором Wi-Fi, кнопка баланса, кнопка `SETTINGS` уменьшенной ширины у правого края и нижняя подпись `SHiNE subserver (v.0.18)`;
|
||||||
- строка Wi-Fi на `HOME` корректно показывает одно из состояний:
|
- строка Wi-Fi на `HOME` корректно показывает одно из состояний:
|
||||||
- `Wi-Fi (not configured) not configured`
|
- `Wi-Fi (not configured) not configured`
|
||||||
- `Wi-Fi (<saved_ssid>) disconnected`
|
- `Wi-Fi (<saved_ssid>) disconnected`
|
||||||
@ -64,9 +64,18 @@
|
|||||||
- `Subserver` открывает промежуточный экран с `USE SUBSERVER1` и `EDIT MANUALLY`;
|
- `Subserver` открывает промежуточный экран с `USE SUBSERVER1` и `EDIT MANUALLY`;
|
||||||
- `USE SUBSERVER1` возвращает стандартное значение `subserver1`;
|
- `USE SUBSERVER1` возвращает стандартное значение `subserver1`;
|
||||||
- `EDIT MANUALLY` открывает общий экран редактирования и сохраняет значение в NVS;
|
- `EDIT MANUALLY` открывает общий экран редактирования и сохраняет значение в NVS;
|
||||||
- `Secret` открывает экран-заглушку, где сказано, что настройка ещё не реализована;
|
|
||||||
- `Secret` теперь открывает меню секрета с показом секрета, ручным вводом и генерацией;
|
- `Secret` теперь открывает меню секрета с показом секрета, ручным вводом и генерацией;
|
||||||
- в `SHOW SECRET` сам секрет показывается увеличенным шрифтом и разбит по `10` символов в строке;
|
- в `SHOW SECRET` показывается прокручиваемый список всех ключей:
|
||||||
|
- `Secret (base58)`
|
||||||
|
- `Root key (base58)`
|
||||||
|
- `Root key priv (base58)`
|
||||||
|
- `Blockchain key (base58)`
|
||||||
|
- `Blockchain key priv (base58)`
|
||||||
|
- `Device key (base58)`
|
||||||
|
- `Device key priv (base58)`
|
||||||
|
- `Subserver key (base58)`
|
||||||
|
- `Subserver key priv (base58)`
|
||||||
|
- значения ключей показываются полными строками увеличенным шрифтом;
|
||||||
- при смене `login` сохранённый секрет сбрасывается в `not set`;
|
- при смене `login` сохранённый секрет сбрасывается в `not set`;
|
||||||
- во время генерации секрета есть `CANCEL` и подтверждение остановки;
|
- во время генерации секрета есть `CANCEL` и подтверждение остановки;
|
||||||
- при отмене генерации старый секрет, если он был, не должен теряться;
|
- при отмене генерации старый секрет, если он был, не должен теряться;
|
||||||
|
|||||||
@ -41,7 +41,8 @@
|
|||||||
- индикатор Wi-Fi уровня сигнала;
|
- индикатор Wi-Fi уровня сигнала;
|
||||||
- по центру крупный текст `STATUS`;
|
- по центру крупный текст `STATUS`;
|
||||||
- одна строка Wi-Fi вида `Wi-Fi (<ssid>) connected/disconnected`;
|
- одна строка Wi-Fi вида `Wi-Fi (<ssid>) connected/disconnected`;
|
||||||
- снизу большую кнопку `SETTINGS`.
|
- кнопка баланса вида `Balance: <value SOL>` или `Balance: failed to load`, по нажатию выполняет повторный запрос;
|
||||||
|
- снизу кнопку `SETTINGS`, уменьшенную примерно до половины ширины экрана и сдвинутую к правому краю.
|
||||||
- внизу на тёмной полосе подпись `SHiNE subserver (v.0.18)`.
|
- внизу на тёмной полосе подпись `SHiNE subserver (v.0.18)`.
|
||||||
|
|
||||||
Строка Wi-Fi на `HOME`:
|
Строка Wi-Fi на `HOME`:
|
||||||
@ -184,10 +185,18 @@
|
|||||||
|
|
||||||
Показывает:
|
Показывает:
|
||||||
- заголовок `SECRET`;
|
- заголовок `SECRET`;
|
||||||
- подпись `Current secret in base58:`;
|
- вертикально прокручиваемый список ключей;
|
||||||
- полный секрет открытым текстом;
|
- `Secret (base58)`;
|
||||||
- увеличенный шрифт для значения секрета;
|
- `Root key (base58)`;
|
||||||
- разбиение секрета по строкам по `10` символов;
|
- `Root key priv (base58)`;
|
||||||
|
- `Blockchain key (base58)`;
|
||||||
|
- `Blockchain key priv (base58)`;
|
||||||
|
- `Device key (base58)`;
|
||||||
|
- `Device key priv (base58)`;
|
||||||
|
- `Subserver key (base58)`;
|
||||||
|
- `Subserver key priv (base58)`;
|
||||||
|
- для каждого поля показывается формула derivation;
|
||||||
|
- значения ключей показываются полными строками увеличенным шрифтом;
|
||||||
- кнопку `BACK`.
|
- кнопку `BACK`.
|
||||||
|
|
||||||
## TEXT_EDIT_SCREEN
|
## TEXT_EDIT_SCREEN
|
||||||
|
|||||||
@ -1,10 +1,15 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
#include <WiFiClientSecure.h>
|
||||||
|
#include <HTTPClient.h>
|
||||||
#include <Preferences.h>
|
#include <Preferences.h>
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
#include <Arduino_GFX_Library.h>
|
#include <Arduino_GFX_Library.h>
|
||||||
#include <TouchDrvCSTXXX.hpp>
|
#include <TouchDrvCSTXXX.hpp>
|
||||||
|
#include <mbedtls/sha256.h>
|
||||||
|
#include <mbedtls/base64.h>
|
||||||
|
#include <Ed25519.h>
|
||||||
#define XPOWERS_CHIP_AXP2101
|
#define XPOWERS_CHIP_AXP2101
|
||||||
#include "XPowersLib.h"
|
#include "XPowersLib.h"
|
||||||
#include "shine_secret_generation.h"
|
#include "shine_secret_generation.h"
|
||||||
@ -87,6 +92,7 @@ enum ActionId {
|
|||||||
ACTION_SECRET_GENERATE_CANCEL_NO,
|
ACTION_SECRET_GENERATE_CANCEL_NO,
|
||||||
ACTION_BACK_SECRET_MENU,
|
ACTION_BACK_SECRET_MENU,
|
||||||
ACTION_BACK_ACCOUNT,
|
ACTION_BACK_ACCOUNT,
|
||||||
|
ACTION_REFRESH_BALANCE,
|
||||||
ACTION_EDITOR_SAVE,
|
ACTION_EDITOR_SAVE,
|
||||||
ACTION_EDITOR_CANCEL,
|
ACTION_EDITOR_CANCEL,
|
||||||
};
|
};
|
||||||
@ -161,6 +167,7 @@ static bool gSecretConfigured = false;
|
|||||||
static String gSecretBase58;
|
static String gSecretBase58;
|
||||||
static uint8_t gSecretBytes[32] = {};
|
static uint8_t gSecretBytes[32] = {};
|
||||||
static String gAccountStatusMessage = "Edit account fields";
|
static String gAccountStatusMessage = "Edit account fields";
|
||||||
|
static String gBalanceStatusMessage = "Balance: tap to load";
|
||||||
static bool gWifiKnownGood = false;
|
static bool gWifiKnownGood = false;
|
||||||
static bool gWifiReconnectEnabled = false;
|
static bool gWifiReconnectEnabled = false;
|
||||||
static bool gWifiOperationBusy = false;
|
static bool gWifiOperationBusy = false;
|
||||||
@ -169,6 +176,21 @@ static unsigned long gWifiLastReconnectAttemptMs = 0;
|
|||||||
static wl_status_t gLastWifiStatus = WL_IDLE_STATUS;
|
static wl_status_t gLastWifiStatus = WL_IDLE_STATUS;
|
||||||
static bool gPowerReady = false;
|
static bool gPowerReady = false;
|
||||||
|
|
||||||
|
struct DerivedKeyInfo {
|
||||||
|
String title;
|
||||||
|
String formula;
|
||||||
|
String value;
|
||||||
|
};
|
||||||
|
|
||||||
|
static String gRootPubB58;
|
||||||
|
static String gRootPrivB58;
|
||||||
|
static String gBlockchainPubB58;
|
||||||
|
static String gBlockchainPrivB58;
|
||||||
|
static String gDevicePubB58;
|
||||||
|
static String gDevicePrivB58;
|
||||||
|
static String gSubserverPubB58;
|
||||||
|
static String gSubserverPrivB58;
|
||||||
|
|
||||||
static EditContext gEditContext = EDIT_CONTEXT_NONE;
|
static EditContext gEditContext = EDIT_CONTEXT_NONE;
|
||||||
static Screen gEditReturnScreen = SCREEN_HOME;
|
static Screen gEditReturnScreen = SCREEN_HOME;
|
||||||
static String gEditTitle;
|
static String gEditTitle;
|
||||||
@ -189,6 +211,7 @@ static void clearSavedWifiList();
|
|||||||
static int findKnownWifiIndex(const String &ssid);
|
static int findKnownWifiIndex(const String &ssid);
|
||||||
static String savedPasswordForSsid(const String &ssid);
|
static String savedPasswordForSsid(const String &ssid);
|
||||||
static void upsertKnownWifi(const String &ssid, const String &password);
|
static void upsertKnownWifi(const String &ssid, const String &password);
|
||||||
|
static bool refreshWalletBalance(String &messageOut);
|
||||||
static void saveServerPrefs();
|
static void saveServerPrefs();
|
||||||
static void saveAccountPrefs();
|
static void saveAccountPrefs();
|
||||||
static void beginSavedWifi();
|
static void beginSavedWifi();
|
||||||
@ -210,6 +233,8 @@ static bool isTextEditKeyboardSwipeArea(int16_t x, int16_t y);
|
|||||||
static void syncEditValueFromTextarea();
|
static void syncEditValueFromTextarea();
|
||||||
static void keepCursorAtEnd();
|
static void keepCursorAtEnd();
|
||||||
static void restoreTextareaFromEditValue();
|
static void restoreTextareaFromEditValue();
|
||||||
|
static void refreshDerivedKeys();
|
||||||
|
static void clearDerivedKeys();
|
||||||
static String loginDisplayValue();
|
static String loginDisplayValue();
|
||||||
static String subserverDisplayValue();
|
static String subserverDisplayValue();
|
||||||
static String homeSecretStatus();
|
static String homeSecretStatus();
|
||||||
@ -380,6 +405,182 @@ static String splitFixedWidth(const String &value, size_t chunkSize) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sha256calc(const uint8_t *in, size_t len, uint8_t *out32) {
|
||||||
|
mbedtls_sha256_context ctx;
|
||||||
|
mbedtls_sha256_init(&ctx);
|
||||||
|
mbedtls_sha256_starts(&ctx, 0);
|
||||||
|
mbedtls_sha256_update(&ctx, in, len);
|
||||||
|
mbedtls_sha256_finish(&ctx, out32);
|
||||||
|
mbedtls_sha256_free(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String base64Std(const uint8_t *data, size_t len) {
|
||||||
|
char out[96] = {};
|
||||||
|
size_t outLen = 0;
|
||||||
|
if (mbedtls_base64_encode(reinterpret_cast<uint8_t *>(out), sizeof(out), &outLen, data, len) != 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
out[min(outLen, sizeof(out) - 1)] = '\0';
|
||||||
|
return String(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String base58From32(const uint8_t *data32) {
|
||||||
|
char out[64] = {};
|
||||||
|
shineSecretBase58Encode(data32, 32, out, sizeof(out));
|
||||||
|
return String(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String subserverKeySuffix() {
|
||||||
|
String name = gSubserverValue;
|
||||||
|
name.trim();
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
name = "subserver1";
|
||||||
|
}
|
||||||
|
return String("subserver.key:") + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deriveKeyPairFromSecretSuffix(const uint8_t *secret32, const String &suffix, String &pubB58, String &privB58) {
|
||||||
|
pubB58 = "";
|
||||||
|
privB58 = "";
|
||||||
|
if (!secret32) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String material = base64Std(secret32, 32) + "|" + suffix;
|
||||||
|
uint8_t seed[32] = {};
|
||||||
|
uint8_t pub[32] = {};
|
||||||
|
sha256calc(reinterpret_cast<const uint8_t *>(material.c_str()), material.length(), seed);
|
||||||
|
Ed25519::derivePublicKey(pub, seed);
|
||||||
|
privB58 = base58From32(seed);
|
||||||
|
pubB58 = base58From32(pub);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clearDerivedKeys() {
|
||||||
|
gRootPubB58 = "";
|
||||||
|
gRootPrivB58 = "";
|
||||||
|
gBlockchainPubB58 = "";
|
||||||
|
gBlockchainPrivB58 = "";
|
||||||
|
gDevicePubB58 = "";
|
||||||
|
gDevicePrivB58 = "";
|
||||||
|
gSubserverPubB58 = "";
|
||||||
|
gSubserverPrivB58 = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void refreshDerivedKeys() {
|
||||||
|
clearDerivedKeys();
|
||||||
|
if (!gSecretConfigured) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
deriveKeyPairFromSecretSuffix(gSecretBytes, "root.key", gRootPubB58, gRootPrivB58);
|
||||||
|
deriveKeyPairFromSecretSuffix(gSecretBytes, "bch.key", gBlockchainPubB58, gBlockchainPrivB58);
|
||||||
|
deriveKeyPairFromSecretSuffix(gSecretBytes, "dev.key", gDevicePubB58, gDevicePrivB58);
|
||||||
|
deriveKeyPairFromSecretSuffix(gSecretBytes, subserverKeySuffix(), gSubserverPubB58, gSubserverPrivB58);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isHttpUrl(const String &url) {
|
||||||
|
return url.startsWith("http://") || url.startsWith("https://");
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool httpPostJson(const String &url, const String &body, int &statusCode, String &payload) {
|
||||||
|
statusCode = -1;
|
||||||
|
payload = "";
|
||||||
|
if (!isHttpUrl(url)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTPClient http;
|
||||||
|
WiFiClientSecure secureClient;
|
||||||
|
WiFiClient plainClient;
|
||||||
|
bool secure = url.startsWith("https://");
|
||||||
|
if (secure) {
|
||||||
|
secureClient.setInsecure();
|
||||||
|
if (!http.begin(secureClient, url)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!http.begin(plainClient, url)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
http.setTimeout(7000);
|
||||||
|
http.addHeader("Content-Type", "application/json");
|
||||||
|
statusCode = http.POST(body);
|
||||||
|
if (statusCode > 0) {
|
||||||
|
payload = http.getString();
|
||||||
|
}
|
||||||
|
http.end();
|
||||||
|
return statusCode > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool jsonInt64Field(const String &json, const String &field, uint64_t &valueOut) {
|
||||||
|
String needle = "\"" + field + "\"";
|
||||||
|
int keyPos = json.indexOf(needle);
|
||||||
|
if (keyPos < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int colon = json.indexOf(':', keyPos + needle.length());
|
||||||
|
if (colon < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int pos = colon + 1;
|
||||||
|
while (pos < (int)json.length() && (json[pos] == ' ' || json[pos] == '\n' || json[pos] == '\r' || json[pos] == '\t')) {
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
int start = pos;
|
||||||
|
while (pos < (int)json.length() && isDigit((unsigned char)json[pos])) {
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
if (pos == start) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
valueOut = strtoull(json.substring(start, pos).c_str(), nullptr, 10);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String formatSolValue(uint64_t lamports) {
|
||||||
|
uint64_t whole = lamports / 1000000000ULL;
|
||||||
|
uint64_t frac = (lamports % 1000000000ULL) / 1000000ULL;
|
||||||
|
char out[48];
|
||||||
|
snprintf(out, sizeof(out), "Balance: %llu.%03llu SOL",
|
||||||
|
(unsigned long long)whole,
|
||||||
|
(unsigned long long)frac);
|
||||||
|
return String(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool refreshWalletBalance(String &messageOut) {
|
||||||
|
messageOut = "";
|
||||||
|
if (WiFi.status() != WL_CONNECTED) {
|
||||||
|
gBalanceStatusMessage = "Balance: Wi-Fi disconnected";
|
||||||
|
messageOut = gBalanceStatusMessage;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (gDevicePubB58.isEmpty()) {
|
||||||
|
gBalanceStatusMessage = "Balance: secret not set";
|
||||||
|
messageOut = gBalanceStatusMessage;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int code = -1;
|
||||||
|
String payload;
|
||||||
|
String req = "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"getBalance\",\"params\":[\"" + gDevicePubB58 + "\",{\"commitment\":\"confirmed\"}]}";
|
||||||
|
if (!httpPostJson(gSolanaRpcUrl, req, code, payload)) {
|
||||||
|
gBalanceStatusMessage = "Balance: failed to load";
|
||||||
|
messageOut = gBalanceStatusMessage;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t lamports = 0;
|
||||||
|
if (!jsonInt64Field(payload, "value", lamports)) {
|
||||||
|
gBalanceStatusMessage = "Balance: failed to load";
|
||||||
|
messageOut = gBalanceStatusMessage;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
gBalanceStatusMessage = formatSolValue(lamports);
|
||||||
|
messageOut = gBalanceStatusMessage;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void upsertKnownWifi(const String &ssid, const String &password) {
|
static void upsertKnownWifi(const String &ssid, const String &password) {
|
||||||
if (ssid.isEmpty()) {
|
if (ssid.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
@ -435,6 +636,8 @@ static void loadPrefs() {
|
|||||||
gSecretBase58 = "";
|
gSecretBase58 = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
refreshDerivedKeys();
|
||||||
|
gBalanceStatusMessage = gDevicePubB58.isEmpty() ? "Balance: secret not set" : "Balance: tap to load";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void saveWifiPrefs() {
|
static void saveWifiPrefs() {
|
||||||
@ -647,6 +850,8 @@ static void clearSecretValue() {
|
|||||||
gSecretConfigured = false;
|
gSecretConfigured = false;
|
||||||
gSecretBase58 = "";
|
gSecretBase58 = "";
|
||||||
memset(gSecretBytes, 0, sizeof(gSecretBytes));
|
memset(gSecretBytes, 0, sizeof(gSecretBytes));
|
||||||
|
refreshDerivedKeys();
|
||||||
|
gBalanceStatusMessage = "Balance: secret not set";
|
||||||
saveAccountPrefs();
|
saveAccountPrefs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,6 +861,8 @@ static void setSecretValue(const uint8_t *bytes32) {
|
|||||||
shineSecretBase58Encode(bytes32, 32, b58, sizeof(b58));
|
shineSecretBase58Encode(bytes32, 32, b58, sizeof(b58));
|
||||||
gSecretBase58 = b58;
|
gSecretBase58 = b58;
|
||||||
gSecretConfigured = true;
|
gSecretConfigured = true;
|
||||||
|
refreshDerivedKeys();
|
||||||
|
gBalanceStatusMessage = "Balance: tap to load";
|
||||||
saveAccountPrefs();
|
saveAccountPrefs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -837,6 +1044,7 @@ static void applyEditorValue() {
|
|||||||
if (gEditContext == EDIT_CONTEXT_SUBSERVER) {
|
if (gEditContext == EDIT_CONTEXT_SUBSERVER) {
|
||||||
value.trim();
|
value.trim();
|
||||||
gSubserverValue = value;
|
gSubserverValue = value;
|
||||||
|
refreshDerivedKeys();
|
||||||
saveAccountPrefs();
|
saveAccountPrefs();
|
||||||
gAccountStatusMessage = gSubserverValue.isEmpty() ? "Subserver cleared" : "Subserver saved";
|
gAccountStatusMessage = gSubserverValue.isEmpty() ? "Subserver cleared" : "Subserver saved";
|
||||||
showScreen(SCREEN_ACCOUNT);
|
showScreen(SCREEN_ACCOUNT);
|
||||||
@ -1103,6 +1311,7 @@ static void actionButtonCb(lv_event_t *event) {
|
|||||||
break;
|
break;
|
||||||
case ACTION_ACCOUNT_SUBSERVER_USE_DEFAULT:
|
case ACTION_ACCOUNT_SUBSERVER_USE_DEFAULT:
|
||||||
gSubserverValue = "subserver1";
|
gSubserverValue = "subserver1";
|
||||||
|
refreshDerivedKeys();
|
||||||
saveAccountPrefs();
|
saveAccountPrefs();
|
||||||
gAccountStatusMessage = "Subserver set to subserver1";
|
gAccountStatusMessage = "Subserver set to subserver1";
|
||||||
showScreen(SCREEN_ACCOUNT);
|
showScreen(SCREEN_ACCOUNT);
|
||||||
@ -1118,6 +1327,17 @@ static void actionButtonCb(lv_event_t *event) {
|
|||||||
case ACTION_BACK_SECRET_MENU:
|
case ACTION_BACK_SECRET_MENU:
|
||||||
showScreen(SCREEN_ACCOUNT_SECRET);
|
showScreen(SCREEN_ACCOUNT_SECRET);
|
||||||
break;
|
break;
|
||||||
|
case ACTION_REFRESH_BALANCE: {
|
||||||
|
String message;
|
||||||
|
gBalanceStatusMessage = "Balance: loading...";
|
||||||
|
rebuildScreen();
|
||||||
|
lv_timer_handler();
|
||||||
|
refreshWalletBalance(message);
|
||||||
|
if (gCurrentScreen == SCREEN_HOME) {
|
||||||
|
rebuildScreen();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ACTION_EDITOR_SAVE:
|
case ACTION_EDITOR_SAVE:
|
||||||
applyEditorValue();
|
applyEditorValue();
|
||||||
break;
|
break;
|
||||||
@ -1221,8 +1441,9 @@ static void drawHome() {
|
|||||||
drawTopStatusIndicators();
|
drawTopStatusIndicators();
|
||||||
makeTitle("STATUS", 150, &lv_font_montserrat_28);
|
makeTitle("STATUS", 150, &lv_font_montserrat_28);
|
||||||
showMessageAt(wifiHomeSummary(), 214);
|
showMessageAt(wifiHomeSummary(), 214);
|
||||||
makeBody("Swipe left or tap the button below.", 274, 360);
|
makeButton(gBalanceStatusMessage.c_str(), 22, 254, 436, 58, 0x355C7D, ACTION_REFRESH_BALANCE, &lv_font_montserrat_18);
|
||||||
makeButton("SETTINGS", 22, 360, 436, 78, 0x2A6F97, ACTION_OPEN_SETTINGS, &lv_font_montserrat_24);
|
makeBody("Swipe left or tap the button below.", 328, 360);
|
||||||
|
makeButton("SETTINGS", 238, 360, 220, 78, 0x2A6F97, ACTION_OPEN_SETTINGS, &lv_font_montserrat_24);
|
||||||
makeVersionTag();
|
makeVersionTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1376,19 +1597,55 @@ static void drawSecretShowScreen() {
|
|||||||
setRootStyle();
|
setRootStyle();
|
||||||
makeTitle("SECRET", 18, &lv_font_montserrat_24);
|
makeTitle("SECRET", 18, &lv_font_montserrat_24);
|
||||||
if (gSecretConfigured) {
|
if (gSecretConfigured) {
|
||||||
showMessageAt("Current secret in base58:", 56);
|
lv_obj_t *panel = lv_obj_create(gRoot);
|
||||||
lv_obj_t *label = lv_label_create(gRoot);
|
lv_obj_set_size(panel, 440, 320);
|
||||||
String secretLines = splitFixedWidth(gSecretBase58, 10);
|
lv_obj_set_pos(panel, 20, 60);
|
||||||
lv_label_set_text(label, secretLines.c_str());
|
lv_obj_set_style_bg_color(panel, lv_color_hex(0x0F1B27), 0);
|
||||||
lv_obj_set_width(label, 420);
|
lv_obj_set_style_bg_opa(panel, LV_OPA_COVER, 0);
|
||||||
lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP);
|
lv_obj_set_style_border_width(panel, 1, 0);
|
||||||
lv_obj_set_style_text_font(label, &lv_font_montserrat_20, 0);
|
lv_obj_set_style_border_color(panel, lv_color_hex(0x425466), 0);
|
||||||
lv_obj_set_style_text_color(label, lv_color_hex(0xD9E1EA), 0);
|
lv_obj_set_style_radius(panel, 14, 0);
|
||||||
lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 102);
|
lv_obj_set_style_pad_all(panel, 14, 0);
|
||||||
|
lv_obj_set_style_pad_row(panel, 8, 0);
|
||||||
|
lv_obj_set_scroll_dir(panel, LV_DIR_VER);
|
||||||
|
lv_obj_set_scrollbar_mode(panel, LV_SCROLLBAR_MODE_ACTIVE);
|
||||||
|
lv_obj_set_flex_flow(panel, LV_FLEX_FLOW_COLUMN);
|
||||||
|
lv_obj_set_flex_align(panel, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
|
||||||
|
|
||||||
|
auto addKeyBlock = [&](const String &title, const String &formula, const String &value) {
|
||||||
|
lv_obj_t *titleLabel = lv_label_create(panel);
|
||||||
|
lv_label_set_text(titleLabel, title.c_str());
|
||||||
|
lv_obj_set_width(titleLabel, 400);
|
||||||
|
lv_obj_set_style_text_font(titleLabel, &lv_font_montserrat_18, 0);
|
||||||
|
lv_obj_set_style_text_color(titleLabel, lv_color_hex(0xFFFFFF), 0);
|
||||||
|
|
||||||
|
lv_obj_t *formulaLabel = lv_label_create(panel);
|
||||||
|
lv_label_set_text(formulaLabel, formula.c_str());
|
||||||
|
lv_obj_set_width(formulaLabel, 400);
|
||||||
|
lv_obj_set_style_text_font(formulaLabel, &lv_font_montserrat_12, 0);
|
||||||
|
lv_obj_set_style_text_color(formulaLabel, lv_color_hex(0x8FA4B8), 0);
|
||||||
|
|
||||||
|
lv_obj_t *valueLabel = lv_label_create(panel);
|
||||||
|
lv_label_set_text(valueLabel, value.c_str());
|
||||||
|
lv_obj_set_width(valueLabel, 400);
|
||||||
|
lv_label_set_long_mode(valueLabel, LV_LABEL_LONG_WRAP);
|
||||||
|
lv_obj_set_style_text_font(valueLabel, &lv_font_montserrat_20, 0);
|
||||||
|
lv_obj_set_style_text_color(valueLabel, lv_color_hex(0xD9E1EA), 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
addKeyBlock("Secret (base58)", "master secret", gSecretBase58);
|
||||||
|
addKeyBlock("Root key (base58)", "pub from sha256(base64(secret)|root.key)", gRootPubB58);
|
||||||
|
addKeyBlock("Root key priv (base58)", "sha256(base64(secret)|root.key)", gRootPrivB58);
|
||||||
|
addKeyBlock("Blockchain key (base58)", "pub from sha256(base64(secret)|bch.key)", gBlockchainPubB58);
|
||||||
|
addKeyBlock("Blockchain key priv (base58)", "sha256(base64(secret)|bch.key)", gBlockchainPrivB58);
|
||||||
|
addKeyBlock("Device key (base58)", "pub from sha256(base64(secret)|dev.key)", gDevicePubB58);
|
||||||
|
addKeyBlock("Device key priv (base58)", "sha256(base64(secret)|dev.key)", gDevicePrivB58);
|
||||||
|
addKeyBlock("Subserver key (base58)", String("pub from sha256(base64(secret)|") + subserverKeySuffix() + ")", gSubserverPubB58);
|
||||||
|
addKeyBlock("Subserver key priv (base58)", String("sha256(base64(secret)|") + subserverKeySuffix() + ")", gSubserverPrivB58);
|
||||||
} else {
|
} else {
|
||||||
showMessageAt("Secret not set", 96);
|
showMessageAt("Secret not set", 96);
|
||||||
}
|
}
|
||||||
makeButton("BACK", 140, 360, 200, 72, 0x5A6570, ACTION_BACK_SECRET_MENU, &lv_font_montserrat_22);
|
makeButton("BACK", 140, 392, 200, 56, 0x5A6570, ACTION_BACK_SECRET_MENU, &lv_font_montserrat_20);
|
||||||
makeVersionTag();
|
makeVersionTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
client.version=1.2.151
|
client.version=1.2.152
|
||||||
server.version=1.2.143
|
server.version=1.2.144
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user