Skip to content

fix: preserve signed electrum unconfirmed balance - #17

Open
noahjoeris wants to merge 2 commits into
bitcoindevkit:masterfrom
noahjoeris:fix/signed-unconfirmed-balance
Open

fix: preserve signed electrum unconfirmed balance#17
noahjoeris wants to merge 2 commits into
bitcoindevkit:masterfrom
noahjoeris:fix/signed-unconfirmed-balance

Conversation

@noahjoeris

Copy link
Copy Markdown

Problem

blockchain.scripthash.get_balance returns unconfirmed as a signed amount. When confirmed coins are spent in the mempool it can be negative. At the moment we simply turn it into a positive amount. Meaning if we receive 1 BTC or if we spend 1 BTC both is shown the same way.
Example: we spend 100 confirmed sats, this results in -100 unconfirmed sats. If we turn it positive a user can think he has now 200 sats (100 sats incoming).

Solution

  • Type unconfirmed as SignedAmount and deserialize with bitcoin::amount::serde::as_sat (preserve the sign).
  • I also switch other sat/BTC amount fields to bitcoin’s as_sat / as_btc helpers and drop the local equivalents.

Electrum returns unconfirmed as a signed mempool delta; simply flipping
the amount to positive can look like BTC received instead of BTC spent.

@caarloshenriq caarloshenriq left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tACK 4c4704e

Reproduced on master: {"confirmed":0,"unconfirmed":-100} deserializes to +100 sat, and on this branch it stays -100 sat. I also A/B tested the second commit against the removed helpers across the sat and BTC paths (zero, negative, i64 bounds, sub satoshi precision, above max money, wrong JSON types) and acceptance and rejection are identical on both sides, so the refactor is behavior preserving.

One thing before merge. There is no test covering the fix: tests/synopsis.rs only prints GetBalanceResp and only ever produces a positive unconfirmed delta, so nothing guards this. Something like:

#[test]
fn get_balance_preserves_negative_unconfirmed() {
    let resp: GetBalanceResp =
        serde_json::from_str(r#"{"confirmed":0,"unconfirmed":-100}"#).unwrap();
    assert_eq!(resp.unconfirmed, SignedAmount::from_sat(-100));
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants