Files
ObsidianDragon/src/wallet/lite_wallet_state_mapper.cpp
DanS 6611d57147 refactor(lite): remove dead parallel refresh/readiness scaffolding (~3.1k lines)
The lite-wallet tree carried a second, unused refresh+readiness architecture
that never reached the shipping binary — exactly the churn CLAUDE.md warns
against. The live refresh path is controller -> gateway.refresh ->
mapLiteWalletRefreshResult -> applyLiteRefreshModelToWalletState; this parallel
stack was dead weight.

Verified unused (their public types/functions are referenced only within the
cluster), then deleted (8 files / 16 incl. headers):
- lite_wallet_refresh_service            (LiteWalletRefreshService + gateway adapters)
- lite_wallet_app_refresh_coordinator
- lite_wallet_app_refresh_orchestrator
- lite_wallet_refresh_readiness_policy
- lite_wallet_state_apply_plan
- lite_wallet_state_apply_executor
- lite_wallet_sync_app_refresh_integration
- lite_wallet_sync_execution_readiness

Severed three thin couplings into the cluster from live files:
- state_mapper: dropped the dead mapLiteWalletRefreshServiceResult and switched
  its include from refresh_service.h to gateway.h (where the live
  LiteWalletRefreshResult/Bundle DTOs actually live).
- server_lifecycle_readiness: dropped the unused syncLifecycleInput member +
  converter and the sync_app_refresh_integration include.
- artifact_resolver: relocated the three LIVE artifact-input structs
  (LiteWalletSdxlArtifact{Symbols,}Input, LiteWalletLinkedBackendReadinessInput)
  out of sync_execution_readiness.h — their only real consumers — into
  artifact_resolver.h, then dropped the include.

Also removed the dead DRAGONX_LONG_LITE_BATCH CMake machinery (its source var
was empty; on Windows it generated a broken lite_batch90_receipt_plan.cpp that
#included an empty path) and the stale .cpp/.h entries in CMakeLists.

Lite source files: 44 -> 30. Lite + full-node configure, both targets build,
test suite passes, source-hygiene clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 12:25:02 -05:00

212 lines
8.0 KiB
C++

#include "wallet/lite_wallet_state_mapper.h"
#include <utility>
namespace dragonx::wallet {
namespace {
LiteWalletAppAddressModel mapAddress(const std::string& address, LiteWalletAppAddressKind kind)
{
LiteWalletAppAddressModel model;
model.address = address;
model.kind = kind;
return model;
}
LiteWalletAppSpendableOutputModel mapSpendableOutput(const LiteSpendableOutput& output)
{
LiteWalletAppSpendableOutputModel model;
model.kind = output.kind;
model.address = output.address;
model.createdInTxid = output.createdInTxid;
model.createdInBlock = output.createdInBlock;
model.valueZatoshis = output.value;
model.spent = output.spent;
model.unconfirmedSpent = output.unconfirmedSpent;
model.pending = output.pending;
model.spendable = output.spendable;
return model;
}
LiteWalletAppTransactionKind mapTransactionKind(LiteTransactionDirection direction)
{
switch (direction) {
case LiteTransactionDirection::Send: return LiteWalletAppTransactionKind::Send;
case LiteTransactionDirection::Receive: return LiteWalletAppTransactionKind::Receive;
case LiteTransactionDirection::Unknown: return LiteWalletAppTransactionKind::Unknown;
}
return LiteWalletAppTransactionKind::Unknown;
}
LiteWalletAppTransactionOutputModel mapTransactionOutput(const LiteTransactionOutput& output)
{
LiteWalletAppTransactionOutputModel model;
model.address = output.address;
model.valueZatoshis = output.value;
model.memo = output.memo;
return model;
}
LiteWalletAppTransactionModel mapTransaction(const LiteTransactionRecord& transaction)
{
LiteWalletAppTransactionModel model;
model.txid = transaction.txid;
model.kind = mapTransactionKind(transaction.direction);
model.timestamp = transaction.datetime;
model.blockHeight = transaction.blockHeight;
model.unconfirmed = transaction.unconfirmed;
model.address = transaction.address;
model.amountZatoshis = transaction.amount;
model.signedAmountZatoshis = model.kind == LiteWalletAppTransactionKind::Send
? -transaction.amount
: transaction.amount;
model.memo = transaction.memo;
model.position = transaction.position;
model.outgoingOutputs.reserve(transaction.outgoingMetadata.size());
for (const auto& output : transaction.outgoingMetadata) {
model.outgoingOutputs.push_back(mapTransactionOutput(output));
}
return model;
}
bool modelHasAnyMappedField(const LiteWalletAppRefreshModel& model)
{
return model.hasChainInfo || model.hasHeight || model.hasBalance || model.hasAddresses ||
model.hasSpendableOutputs || model.hasTransactions || model.hasSyncStatus;
}
void addIssue(LiteWalletStateMapResult& result, LiteWalletStateMapIssue issue, std::string message)
{
result.issues.push_back(LiteWalletStateMapIssueInfo{issue, std::move(message)});
}
} // namespace
const char* liteWalletAppAddressKindName(LiteWalletAppAddressKind kind)
{
switch (kind) {
case LiteWalletAppAddressKind::Shielded: return "shielded";
case LiteWalletAppAddressKind::Transparent: return "transparent";
}
return "unknown";
}
const char* liteWalletAppTransactionKindName(LiteWalletAppTransactionKind kind)
{
switch (kind) {
case LiteWalletAppTransactionKind::Unknown: return "unknown";
case LiteWalletAppTransactionKind::Send: return "send";
case LiteWalletAppTransactionKind::Receive: return "receive";
}
return "unknown";
}
const char* liteWalletStateMapIssueName(LiteWalletStateMapIssue issue)
{
switch (issue) {
case LiteWalletStateMapIssue::EmptyBundle: return "EmptyBundle";
case LiteWalletStateMapIssue::IncompleteBundle: return "IncompleteBundle";
}
return "Unknown";
}
LiteWalletStateMapResult mapLiteWalletRefreshBundle(const LiteWalletRefreshBundle& bundle)
{
LiteWalletStateMapResult result;
result.stateMutationAllowed = false;
result.model.complete = bundle.complete;
result.model.successfulCommandCount = bundle.successfulCommandCount;
if (bundle.hasInfo) {
result.model.hasChainInfo = true;
result.model.chain.chainName = bundle.info.chainName;
result.model.chain.version = bundle.info.version;
result.model.chain.vendor = bundle.info.vendor;
result.model.chain.latestBlockHeight = bundle.info.latestBlockHeight;
result.model.chain.difficulty = bundle.info.difficulty;
result.model.chain.longestChain = bundle.info.longestChain;
result.model.chain.notarized = bundle.info.notarized;
}
if (bundle.hasHeight) {
result.model.hasHeight = true;
result.model.height.height = bundle.height.height;
}
if (bundle.hasBalance) {
result.model.hasBalance = true;
result.model.balance.transparentZatoshis = bundle.balance.transparentBalance;
result.model.balance.shieldedZatoshis = bundle.balance.shieldedBalance;
result.model.balance.unconfirmedZatoshis = bundle.balance.unconfirmedBalance;
result.model.balance.verifiedShieldedZatoshis = bundle.balance.verifiedShieldedBalance;
result.model.balance.spendableShieldedZatoshis = bundle.balance.spendableShieldedBalance;
result.model.balance.totalZatoshis = bundle.balance.transparentBalance + bundle.balance.shieldedBalance;
}
if (bundle.hasAddresses) {
result.model.hasAddresses = true;
result.model.addresses.reserve(bundle.addresses.zAddresses.size() + bundle.addresses.tAddresses.size());
for (const auto& address : bundle.addresses.zAddresses) {
result.model.addresses.push_back(mapAddress(address, LiteWalletAppAddressKind::Shielded));
}
for (const auto& address : bundle.addresses.tAddresses) {
result.model.addresses.push_back(mapAddress(address, LiteWalletAppAddressKind::Transparent));
}
}
if (bundle.hasNotes) {
result.model.hasSpendableOutputs = true;
const auto outputCount = bundle.notes.unspentNotes.size() + bundle.notes.utxos.size() +
bundle.notes.pendingNotes.size() + bundle.notes.pendingUtxos.size();
result.model.spendableOutputs.reserve(outputCount);
for (const auto& output : bundle.notes.unspentNotes) {
result.model.spendableOutputs.push_back(mapSpendableOutput(output));
}
for (const auto& output : bundle.notes.utxos) {
result.model.spendableOutputs.push_back(mapSpendableOutput(output));
}
for (const auto& output : bundle.notes.pendingNotes) {
result.model.spendableOutputs.push_back(mapSpendableOutput(output));
}
for (const auto& output : bundle.notes.pendingUtxos) {
result.model.spendableOutputs.push_back(mapSpendableOutput(output));
}
}
if (bundle.hasTransactions) {
result.model.hasTransactions = true;
result.model.transactions.reserve(bundle.transactions.transactions.size());
for (const auto& transaction : bundle.transactions.transactions) {
result.model.transactions.push_back(mapTransaction(transaction));
}
}
if (bundle.hasSyncStatus) {
result.model.hasSyncStatus = true;
result.model.sync.walletHeight = bundle.syncStatus.syncedBlocks;
result.model.sync.chainHeight = bundle.syncStatus.totalBlocks;
result.model.sync.progress = bundle.syncStatus.progress;
result.model.sync.complete = bundle.syncStatus.complete;
}
if (!modelHasAnyMappedField(result.model)) {
addIssue(result, LiteWalletStateMapIssue::EmptyBundle, "lite refresh bundle has no mappable fields");
result.error = result.issues.back().message;
return result;
}
if (!bundle.complete) {
addIssue(result, LiteWalletStateMapIssue::IncompleteBundle, "lite refresh bundle is partial");
}
result.ok = true;
return result;
}
LiteWalletStateMapResult mapLiteWalletRefreshResult(const LiteWalletRefreshResult& result)
{
return mapLiteWalletRefreshBundle(result.bundle);
}
} // namespace dragonx::wallet