Skip to content

wallet balance --mint reports a whole-wallet total_sats that excludes-but-counts filtered mints (#668 follow-up) #679

Description

@orveth

Follow-up nit from the #668 review (merged as fc6992cf). Display only — no money path is affected, nothing spends on this value.

What changed

#668 moved the total computation in cmd_balance from inside the row loop (after the --mint filter's continue) to before it, over all rows:

// main before #668 — accumulated after the filter, so `total` was the FILTERED total
for row in &rows {
    if let Some(filter) = filter.as_deref() {
        if row.mint_url != filter { continue; }
    }
    total = total.saturating_add(row.balance_sats);   // <- only matched rows
    ...
}

// after #668 — computed over ALL rows, before the loop
let total = rows.iter().map(|row| row.balance_sats).fold(0u64, u64::saturating_add);

So maxplayer wallet balance --mint <X> now reports a total_sats that includes mints the filter excluded and which appear nowhere in the output.

Measured

Fixture: configured testnut default seeded with 100 sats, plus an unconfigured https://stray-mint.example/ seeded with 41. Command: wallet balance --mint https://testnut.cashudevkit.org.

mint=https://testnut.cashudevkit.org role=default balance_sats=100 play_money=true
configured_total_sats=100
total_sats=141

The 41 sats come from a mint that was filtered out. On main before #668 this printed total_sats=100. configured_total_sats ignores the filter for the same reason.

Why it survived review

balance_mint_filter_distinguishes_discovered_from_never_seen asserts only the row line, never the total. In its fixture the default holds 0, so the filtered total and the whole-wallet total are both 41 — the two semantics are byte-identical in that output, and no test discriminates them.

Suggested fix

Either scope both totals to the matched rows when --mint is present, or leave them whole-wallet and label them so the number is not read as being about the filtered mint. Whichever is chosen, add a test whose fixture makes the filtered and whole-wallet totals differ, so the assertion can tell them apart.

Note the agent-facing contract in web/app/.well-known/skills/buyer-operate/skill.md says "total_sats is whole-wallet spendable sats", which is now unconditionally true — but under --mint it reads as a total for the mint that was asked about.

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