ESP32: исправить ABI регистрации и подробные ошибки RPC

This commit is contained in:
AidarKC 2026-06-12 23:43:42 +04:00
parent 3262ec9b4a
commit b583a86ade
3 changed files with 103 additions and 8 deletions

View File

@ -362,6 +362,9 @@ static bool rpcCallSolana(const char *method, const String &paramsJson, String &
static bool rpcResponseHasError(const String &payload);
static bool getLatestBlockhashBytes(uint8_t out[32], String &blockhashB58, String &messageOut);
static bool pdaAlreadyExists(const String &login, String &pdaAddress, String &messageOut);
static bool extractRpcErrorSummary(const String &payload, String &messageOut);
static String compactRpcLogs(const String &payload, int maxLines = 3);
static bool simulateTransactionForError(const String &txBase64, String &messageOut);
static std::vector<uint8_t> buildLastBlockStateBytes(const String &login, const String &blockchainName);
static std::vector<uint8_t> buildUnsignedCreateRecord(
const String &login,
@ -1223,6 +1226,7 @@ static std::vector<uint8_t> buildCreateInstructionData(
out.push_back(0);
out.push_back(1);
out.push_back(0);
out.push_back(0);
pushStrU8(out, serverAddress);
out.push_back(0);
out.push_back(0);
@ -1298,6 +1302,86 @@ static bool pdaAlreadyExists(const String &login, String &pdaAddress, String &me
return false;
}
static String compactRpcLogs(const String &payload, int maxLines) {
String out;
int pos = payload.indexOf("\"logs\"");
if (pos < 0) {
return "";
}
int bracket = payload.indexOf('[', pos);
if (bracket < 0) {
return "";
}
int i = bracket + 1;
int lines = 0;
while (i < (int)payload.length() && lines < maxLines) {
while (i < (int)payload.length() && payload[i] != '"' && payload[i] != ']') {
i++;
}
if (i >= (int)payload.length() || payload[i] == ']') {
break;
}
String line;
bool escape = false;
i++;
for (; i < (int)payload.length(); ++i) {
char ch = payload[i];
if (escape) {
switch (ch) {
case 'n': line += ' '; break;
case 'r': break;
case 't': line += ' '; break;
default: line += ch; break;
}
escape = false;
continue;
}
if (ch == '\\') {
escape = true;
continue;
}
if (ch == '"') {
i++;
break;
}
line += ch;
}
line.trim();
if (!line.isEmpty()) {
if (!out.isEmpty()) {
out += " | ";
}
out += line;
lines++;
}
}
return out;
}
static bool extractRpcErrorSummary(const String &payload, String &messageOut) {
messageOut = "";
String errorMessage;
if (jsonStringField(payload, "message", errorMessage) && !errorMessage.isEmpty()) {
messageOut = errorMessage;
}
String logs = compactRpcLogs(payload, 3);
if (!logs.isEmpty()) {
if (!messageOut.isEmpty()) {
messageOut += " | ";
}
messageOut += logs;
}
return !messageOut.isEmpty();
}
static bool simulateTransactionForError(const String &txBase64, String &messageOut) {
String payload;
if (!rpcCallSolana("simulateTransaction", "[\"" + txBase64 + "\",{\"encoding\":\"base64\",\"sigVerify\":true,\"commitment\":\"processed\"}]", payload)) {
return false;
}
return extractRpcErrorSummary(payload, messageOut);
}
static std::vector<uint8_t> buildLegacyMessage(
const uint8_t recentBlockhash[32],
const uint8_t devicePub[32],
@ -1531,7 +1615,17 @@ static bool registerHomeserverOnSolana(String &messageOut) {
return false;
}
if (rpcResponseHasError(payload)) {
messageOut = "RPC returned sendTransaction error";
if (!extractRpcErrorSummary(payload, messageOut)) {
messageOut = "RPC returned sendTransaction error";
}
String simulated;
if (simulateTransactionForError(txBase64, simulated)) {
if (messageOut.isEmpty()) {
messageOut = simulated;
} else if (messageOut.indexOf(simulated) < 0) {
messageOut += " | simulate: " + simulated;
}
}
return false;
}
if (!awaitTransactionConfirmation(signatureB58, messageOut)) {
@ -3085,13 +3179,13 @@ static void actionButtonCb(lv_event_t *event) {
String registerMessage;
if (registerHomeserverOnSolana(registerMessage)) {
gRegisterResultSuccess = true;
gRegisterResultMessage = "Registration in SHiNE completed";
gRegisterResultDetails = registerMessage;
gRegisterResultMessage = registerMessage;
gRegisterResultDetails = String("user_pda and tx signature were saved");
gAccountStatusMessage = "Registration completed";
} else {
gRegisterResultSuccess = false;
gRegisterResultMessage = "Registration failed";
gRegisterResultDetails = registerMessage;
gRegisterResultMessage = registerMessage;
gRegisterResultDetails = "";
gAccountStatusMessage = registerMessage;
}
gRegisterConfirmMessage = "";

View File

@ -212,7 +212,8 @@
Поведение:
- после успешной регистрации данные `user_pda` и `tx signature` сохраняются в `NVS`;
- при ошибке на экране показывается причина отказа.
- при ошибке на экране показывается причина отказа;
- если ошибку вернул `sendTransaction`, экран старается показать не только общий текст, но и детали `RPC`/preflight/simulate-логов.
## Экран STATUS

View File

@ -1,2 +1,2 @@
client.version=1.2.166
server.version=1.2.155
client.version=1.2.167
server.version=1.2.156