feat(chat): harvest chat memos on the lite variant (lite receive)
The full-node receive harvest works off z_viewtransaction; the lite wallet's transactions come from the backend instead, so lite chat receive was unwired. App::ingestLiteChatMemos runs after each lite refresh: the backend lists one entry per received (non-change) note — same txid, distinct position + decoded UTF-8 memo — so a chat tx yields two entries (header + payload). Group the Receive-kind notes by txid, feed them through the SAME extractHushChatTransaction Metadata parser (now order-tolerant, so the daemon's output shuffle is a non-issue), and thread the result into ChatService. The store dedups (txid+position), so re-listing every refresh is harmless. This closes the lite variant's chat loop end-to-end: identity (exportSeed), DB unlock/load, receive (here), UI, and send (broadcastChatMemosLite). Gated by DRAGONX_ENABLE_CHAT (default OFF). Verified: Linux + Windows build with chat ON, ctest 100%, hygiene clean; caches restored to OFF. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -38,6 +38,7 @@
|
||||
#include <cctype>
|
||||
#include "config/settings.h"
|
||||
#include "wallet/lite_wallet_controller.h" // lite send/new-address routing
|
||||
#include "wallet/lite_wallet_state_mapper.h" // LiteWalletAppRefreshModel for lite chat harvest
|
||||
#include "daemon/daemon_controller.h"
|
||||
#include "daemon/embedded_daemon.h"
|
||||
#include "daemon/xmrig_manager.h"
|
||||
@@ -2630,6 +2631,35 @@ void App::startChatConversation(const std::string& peerZaddr, const std::string&
|
||||
ui::Notifications::instance().success("Contact request queued.");
|
||||
}
|
||||
|
||||
// HushChat (lite variant): the full-node harvest works off z_viewtransaction, but the lite wallet's
|
||||
// transactions come from the backend. The backend lists one entry per received (non-change) note —
|
||||
// same txid, distinct position + decoded-UTF-8 memo — so a chat tx yields two entries (header +
|
||||
// payload). Group the received notes by txid, run them through the SAME parser, and thread the
|
||||
// result. The store dedups (txid+position), so re-listing every refresh is harmless.
|
||||
void App::ingestLiteChatMemos(const wallet::LiteWalletAppRefreshModel& model)
|
||||
{
|
||||
if (!chat::hushChatFeatureEnabledAtBuild() || !chat_service_.hasIdentity()) return;
|
||||
|
||||
std::unordered_map<std::string, chat::HushChatTransactionInput> byTxid;
|
||||
std::unordered_map<std::string, std::int64_t> txTimestamps;
|
||||
for (const auto& tx : model.transactions) {
|
||||
if (tx.kind != wallet::LiteWalletAppTransactionKind::Receive) continue; // only incoming carry chat
|
||||
if (tx.memo.empty() || !tx.position) continue;
|
||||
auto& input = byTxid[tx.txid];
|
||||
input.txid = tx.txid;
|
||||
input.outputs.push_back({static_cast<std::size_t>(*tx.position), tx.memo});
|
||||
txTimestamps[tx.txid] = tx.timestamp;
|
||||
}
|
||||
if (byTxid.empty()) return;
|
||||
|
||||
std::vector<chat::HushChatTransactionMetadata> metadata;
|
||||
for (auto& entry : byTxid) {
|
||||
auto extracted = chat::extractHushChatTransactionMetadata(entry.second, true);
|
||||
for (auto& meta : extracted.metadata) metadata.push_back(std::move(meta));
|
||||
}
|
||||
if (!metadata.empty()) chat_service_.ingest(metadata, txTimestamps, std::time(nullptr));
|
||||
}
|
||||
|
||||
void App::exportAllKeys(std::function<void(const std::string&, int, int)> callback)
|
||||
{
|
||||
if (!state_.connected || !rpc_) {
|
||||
|
||||
Reference in New Issue
Block a user