Skip to content

platform-wallet: AssetLock persisted as INTERNAL/net-0 — the OP_RETURN burn+fee spend is invisible to net-based consumers #4412

Description

@bfoss765

Summary

An AssetLock (identity credit-funding) transaction is persisted to the wallet store's transactions row as direction = INTERNAL, netAmount = 0, even though the wallet irreversibly spends the OP_RETURN burn plus the L1 fee. Field case (mainnet wallet, 2025-01-21): a credit purchase burning 0.03 DASH with a 241-duff fee — true wallet net −0.03000241 — stored as net-0 INTERNAL, making the purchase invisible to every net-based consumer (history sums, CSV/tax export, balance reconciliation).

This was isolated by a full duff-level reconciliation of a field wallet against its on-chain history: the stored-net sum over all 134 transactions differed from the UTXO-derived balance by exactly the AssetLock's burn+fee (plus one #4387 case — separate issue).

Why it happens

The persistence-side net computation treats the asset lock as entirely-self: every address-bearing output (the change) returns to owned addresses, and the value-bearing OP_RETURN output has no address, so nothing is counted as leaving the wallet. The burn is real spend: those duffs become Platform credits and never return to L1.

Expected

netAmount = −(op_return_burn + fee) and a non-INTERNAL classification (OUTGOING, or a dedicated kind if consumers want to render "credit purchase" distinctly — the transactionType = AssetLock column already distinguishes it).

Workaround shipped app-side (Android)

The exporter now includes entirely-self transactions with a value-bearing OP_RETURN as an Expense valued −(burn+fee), so tax exports reconcile. That branch is written to go inert once the store persists the true net (it only fires on netAmount == 0).

Scope note

Related but distinct from #4387 (multi-account spend persisting a per-account net slice): both are persistence-side netAmount truth defects, and a fix PR could reasonably cover both paths in rs-platform-wallet's transaction recording.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions