Skip to content

fix(wallet): surface unresolved Platform funding transfers - #1028

Draft
lklimek wants to merge 20 commits into
v1.0-devfrom
fix/orphaned-tx
Draft

lklimek wants to merge 20 commits into
v1.0-devfrom
fix/orphaned-tx

Conversation

@lklimek

@lklimek lklimek commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

TL;DR: Integrate Core-to-Platform funding into ordinary Dash Core transaction rows, with details and recorded payment conflicts. Recovered historical funding is not presented as a pending transfer. New payments stop before signing when confirmed history contradicts the wallet’s available funds. Cancellation and verified Platform delivery checks remain unavailable.

User story

As a wallet user, I want to find an interrupted transfer in my transaction history and understand what the wallet actually knows about it.

Scenario

Base flow

A transfer to Platform does not receive confirmation, and the user reopens the wallet.

Actual behavior

The pending entry sorts below dated payments, and the history does not explain a competing payment using the same funds.

Expected behavior

The transfer appears once inside Dash Core Transactions, with its confirmation status, a Details action, and any recorded input conflict. Historical funding stays in chronological history. The user can distinguish local records from verified delivery information.

Detailed discussion

What was done

  • Before signing a Core payment or new asset lock (including identity, Platform-address, and shielded funding), compare live funding outpoints against persisted confirmed transaction inputs. Fail closed on conflicts or unreadable records; existing asset-lock continuation is unchanged. The check reads technical records retained across visible-history resets.
  • Platform dependencies track Platform fix/pr-5126 at c0425f7bdcc29776f6d5f0f35a56cde7eb368c7f, including its rust-dashcore pin 18f7f3e6, for persisted Core transaction accounting reconciliation and confirmed-spend restoration on SQLite load. Document field handling supports the new typed-array and key-reference variants; identity balance lookup failures retain typed error classification. This is an unmerged upstream dependency. The SQLite loader replays confirmed records through the wallet checker and restores finality before sync checkpoint pruning, preventing old funding from resurrecting spent outputs. It uses dash_async::block_on with no additional executor. DET's preflight remains enabled. The new InvitationNetworkMismatch error is handled in the existing exhaustive error classifiers.
  • Full resync durably clears the selected wallet’s displayed transaction history. Wallet-scoped reset markers prevent old rows from returning after restart; verified block observations rebuild history even when upstream skips finalized record events. Technical Core records are retained for spend accounting, along with reservations and Platform transfer state. This is a history reset, not transaction cancellation. Interrupted scans require Full resync again.
  • Merge tracked funding and hydrated Core history by TXID. Keep funding-only records visible, sort unconfirmed rows first, and retain confirmed rows in date order.
  • Classify RecoveredFromChain separately: unknown Platform consumption does not establish an unfinished transfer. Keep transfer information in transaction history, without a separate review summary or View transfers shortcut.
  • Group Copy, View, Details, and disabled cancellation in the final Actions column, using the existing compact button style.
  • Group Import key, Refresh, Full resync, and Testnet-only Get test DASH under Advanced.
  • Full resync rewinds only the selected HD wallet’s Core filter checkpoint to genesis through the upstream manager API, off the async executor. It preserves wallet records and requires Core to be connected and synced. A blocking overlay reuses the initial-sync progress and cancellation flow. It stays up until the selected wallet reaches its target and the Core pipeline is synced, including the interval before fresh sync status arrives. Matching task completion/failure clears it; unrelated results cannot dismiss it. The request must be repeated after an app restart if the scan was interrupted.
  • Use the existing Refresh action to reload transfer records after wallet refresh completes, retaining one follow-up read when an earlier read is in flight. There is no separate record-refresh button.
  • Show funding information in row details, with optional Core explorer links and explicit unknown recipient/Platform outcome.
  • Show a disabled Cancel transfer action for unconfirmed funding with the backend limitation explained; do not imply that deleting records returns funds.
  • Use scoped async assessments, request coalescing, timeout handling, and stale wallet/network/request rejection. Close details on wallet/network changes.
  • Keep doctests in the main CI suite only, and use Cargo directly for test execution.

Limits

The preflight is a conservative wallet-wide consistency check, not an atomic selected-input check or proof against unknown spends. An inconsistent output can block an otherwise fundable payment. It does not repair the live UTXO set, cancel existing transactions, or release reservations.

Automatic conflict cleanup already exists upstream through TransactionsSwept, and DET handles those events. The missing operation is safe reconciliation/cancellation of historical conflicts found only in persisted DET history; the signed, unsent Core-payment abandonment API cannot substitute for it.

The pinned wallet lacks verified finalized ancestry, atomic conflict reconciliation, durable asset-lock cancellation/rebroadcast control, and verified consumption lookup for every recovered lock. Safe cancellation, automatic reconciliation, and verified continuation remain WAL-034 gaps. No timeout-based release, record deletion, fund movement, or new secret storage is introduced.

Validation

  • Follow-up on the three non-configuration E2E failures: the targeted run passed DashPay profile registration and the full shielded lifecycle (withdrawal raised to 50,000,000 credits); TC-018 still fails with AssetLockAddressNotFound after matching the exact new TXID and duff amount. Diagnostics show a valid tracked lock/proof but no credit-output address in DET's Wallet::known_addresses; the manual funding path's local key lookup remains a production gap. The fixture now waits for final, unreserved asset-lock inputs instead of counting unconfirmed display funds, polls shielded balance propagation with a timeout, and recovers leftover test funds before enforcing the suite budget. The historical DashPay failure was not reproduced with detailed telemetry; the premature-readiness bug is confirmed in code. Existing finality unit test and scoped backend E2E Clippy passed.
  • Current pin: formatting and cargo clippy --locked --test backend-e2e --all-features -- -D warnings pass. The upstream fix restores confirmed spend/finality state; rust-dashcore is unchanged.
  • Upstream regression was reproduced before the fix; 47 targeted storage tests now pass, including 8 restart/finality/reservation regressions. Loading a private copy of the existing E2E database restored 38 wallets with zero live UTXO/confirmed-history conflicts. The framework wallet restored 14 UTXOs and 10.74146576 DASH, versus the earlier inflated 105.03792631 DASH.
  • Live testnet validation on DET 2383a0aa2 / Platform c0425f7bdc / rust-dashcore 18f7f3e6: the standalone Core payment round trip passed; the full network-dependent backend E2E run finished with 65 passed and 10 failed (75 executed, 18 non-network tests filtered out). Seven failures require the unset E2E_MN_PAYOUT_KEY; the other failures were DashPay identity funding (AssetLockInsufficientFunds), shielded withdrawal (balance mismatch), and asset-lock address funding (AssetLockAddressNotFound). Core payment round trip and cold-process wallet migration/balance recovery passed. No WalletConfirmedInputConflict occurred in this run. The suite is not green; the three other failures have not been root-caused.
  • cargo test --lib spend_history --all-features: regression covers rejection through the payment entrypoint before signing, history reset, wallet/outpoint isolation, pending records, unchanged live funds, and corrupt-record failure.
  • Reproduced the UI regression before fixing it: no Unconfirmed row in the Core table.
  • cargo test --lib pending_transfers --all-features: 16 passed, including merge/order, recovered-history semantics, Refresh ordering, and light/dark/narrow-layout UI tests. Layout assertions cover final-column placement, button ordering and equal height, horizontal scrolling, and opening details at 420 px.
  • cargo test --test kittest wallets_screen --all-features: 18 passed.
  • cargo test --lib full_resync --all-features: 5 passed, including durable history reset, failed persistence, selected-wallet isolation, block replay, preservation of upstream records, selected-wallet checkpoint rewind, preservation of other wallets, unknown wallets, disconnected/busy rejection, and overlay completion/cancellation while the previous status remains Synced.
  • cargo test --test kittest task9_spv --all-features: 2 passed, covering initial-sync blocking and keyboard-safe cancellation.
  • cargo test --lib advanced_ --all-features: 15 passed, including popup interaction in both themes, wallet action availability, and faucet exclusion on Mainnet.
  • Scoped local Clippy (--all-features --lib --tests -- -D warnings) and cargo fmt --all passed.
  • Live Testnet diagnosis was read-only. The reported transaction remains unconfirmed in local history, and 31 funding records of 0.01 DASH are marked recovered_from_chain. Explorer evidence confirms the recorded competing spend; it is not used to authorize cancellation.
  • Original user wallet files were inspected read-only. Authorized fund-moving tests use the isolated backend-e2e testnet wallet/configuration.

🤖 Co-authored by Claudius the Magnificent AI Agent

Expose pending funding and provisional input conflicts in wallet-level history.
Keep cancellation and release disabled until upstream supports safe reconciliation.

Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
@coderabbitai

coderabbitai Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@thepastaclaw

thepastaclaw commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

🕓 Review not started yet because this PR is a draft.

  • Request normal review — click when the PR is ready for review.
  • Request priority review — click to move this review to the front of the queue.

Commit 83ad4c2. Normal review starts when eligible; priority review starts as soon as a slot is available.

Use arrays in fixed-size test fixtures and run documentation tests only
through the main Cargo test suite. Replace the retired Cargo action with
a direct command and align CI guidance with manual draft checks.

Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
@lklimek lklimek added the claudius-review Triggers automated code review using claudius plugin, runs as a CI job label Sep 25, 2026
lklimek and others added 17 commits September 25, 2026 10:49
Merge funding observations with Core history and expose row details.
Separate recovered historical funding from pending transfers, label local
refresh accurately, and explain the unsupported cancellation action.

Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
Group compact transaction buttons in the final Actions column. Reload
funding records after wallet refresh, coalescing an in-flight follow-up.
Document the distinction between live conflict cleanup and the missing
historical asset-lock cancellation operation upstream.

Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
Move key import, refresh, and the Testnet faucet into Advanced.
Request a selected-wallet Core scan from genesis without deleting records.

Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
Keep the initial-sync overlay open until the selected wallet and Core
pipeline catch up. Scope completion to the dispatched scan and retain
the existing two-step cancellation flow.

Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
Use platform PR #4777 head f2c162ab and adapt to the new document
property types and identity balance error.

Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
Restore the original Platform pin. Persist wallet-scoped history reset
markers and rebuild display history from block observations, including
records whose finalized events upstream omits. Preserve upstream spend
accounting, reservations, and Platform transfer data.

Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
Check live funding outputs against persisted confirmed transaction records
before Core payments and new asset locks. Preserve the guard across visible
history resets, and fail closed when records cannot be checked.

Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
Track platform PR #4814 at 81f1a1c7 and adapt document property types
and identity balance errors to its updated base.

Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
Track fix/pr-5126 at 60e1f6de and handle the new invitation error
in exhaustive wallet error classifiers.

Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
Pin fix/pr-5126 at 82cec940 with rust-dashcore 18f7f3e6.

Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
Platform moves to 37ea1bbb; rust-dashcore remains at 18f7f3e.
The upstream diff changes only its PR hygiene workflow.

Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
Use Platform c0425f7b to rebuild confirmed spending and finality guards
from persisted Core history before sync can redeliver old funding.
Keep the existing rust-dashcore pin and DET pre-send consistency check.

Co-authored-by: Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
Use the asset-lock input snapshot before returning funded test wallets,
recover prior test funds before budget checks, and await shielded balance
propagation. Raise the withdrawal amount and match asset locks by TXID and
duffs. Retain diagnostics exposing the remaining DET signing-key lookup bug.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Resolve CHANGELOG.md conflicts by keeping both sides' additive entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lklimek added a commit that referenced this pull request Oct 2, 2026
…1042)

* feat(ui): add toolbar dropdown menu support

Bring over the generic toolbar dropdown infrastructure from #1028
(ToolbarMenuItem and DesiredAppAction::Menu, rendered as a popup by the
top panel) so other screens can group actions behind one button.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(identity): let users load an identity from the Identities page

Users with identities already loaded had no way to reach "Load an
existing identity" from the picker: the add card promised create or
load but only opened creation, and the identity pill's dropdown needs
a selected identity.

Add an "Add" dropdown to the Identities top bar (create, load, and the
Power-user test-identities entry, matching the pill's dropdown) and make
the "Add a new identity" card open the same choices. Both route through
the hub's existing breadcrumb add effects, so creation keeps the
selected wallet preselected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(identity): drop the unwired "Create multiple test identities" entry

No bulk-creation screen exists, so the entry only opened the single
identity creation screen. Remove it from the Add menu and the identity
pill dropdown until IDH-005 is implemented. Also route the picker scroll
test through the Add card's new create/load menu.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): share action menus and cover identity wallet preselection

Clarify the identity menu documentation, consolidate four popup renderers,
and assert selected-wallet preservation through toolbar and picker creation.

Co-Authored-By: OpenAI Codex <noreply@openai.com>

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>

* fix(ui): align dropdown rows and enlarge menu indicators

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@lklimek lklimek added the blocked Blocked by something external to this issue label Oct 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocked Blocked by something external to this issue claudius-review Triggers automated code review using claudius plugin, runs as a CI job

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants