Thanks to visit codestin.com
Credit goes to github.com

Skip to content

FIX: include recovering funds in Arkade balance & guard sends against them#8747

Open
pietro909 wants to merge 4 commits into
masterfrom
fix-ark-pending-recovery-balance
Open

FIX: include recovering funds in Arkade balance & guard sends against them#8747
pietro909 wants to merge 4 commits into
masterfrom
fix-ark-pending-recovery-balance

Conversation

@pietro909

@pietro909 pietro909 commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

FIX: include recovering funds in Arkade balance & guard sends against them

Problem

After a signer-rotation cutoff, an imported Arkade wallet holding only deprecated-signer funds (pendingRecovery) showed a balance of 0 — the headline was available + recoverable, which omits that leg. But those funds also can't be spent until the server sweeps them, so simply displaying them would let a send fail with a bare insufficient funds that contradicts the on-screen amount.

Changes

  • Balance = total − boarding.total (includes pendingRecovery), consistent across fetchBalance() and the swap-event refresh.
  • Send guard: when a Lightning send exceeds the truly-spendable balance and pendingRecovery > 0, payInvoice throws a clear "funds still recovering" message and skips the swap — with a concrete sweep ETA when the SDK advertises one.

Screenshot

image

Testing

Added unit coverage for the guard and ETA rendering; 73 tests passing in lightning-ark-wallet.test.ts.

pietro909 added 4 commits July 6, 2026 12:45
After a server signer-rotation cutoff, an imported Arkade wallet whose
funds are all deprecated-signer VTXOs showed a balance of 0. SDK 0.4.35
puts such funds in the new WalletBalance.pendingRecovery bucket, which is
excluded from `available`/`recoverable` but still counted in `total`.

fetchBalance() (and the swap-event refresh handler) summed
`available + recoverable`, dropping pendingRecovery. Switch both to
`total - boarding.total`, which keeps boarding excluded (same double-count
rationale) while including pendingRecovery — the user's money, pending the
SDK's automatic migration.
The displayed Arkade balance includes `pendingRecovery` (deprecated-signer
funds past their rotation cutoff), but the SDK's send coin-selection
excludes those VTXOs until the Ark server sweeps them. Paying against a
balance that is mostly pendingRecovery therefore failed with a bare
"insufficient funds" that contradicts the on-screen amount.

Detect that case in payInvoice and throw an honest message telling the
user the funds are recovering and how many sats are spendable now.
When a send is blocked because the balance is mostly pendingRecovery,
surface a concrete ETA instead of open-ended wording. Each deprecated-
signer report carries `nextSweepEta` (ms epoch of the soonest batch
expiry = when the server sweeps those VTXOs and they become spendable);
take the earliest across signers and render it with the app's relative
time helper ("… should become available in 2 days"). Falls back to the
open-ended message when no future ETA is advertised.

Also add getBalance/getVtxoManager to the payInvoice test mock and cover
the recovering-funds guard (with and without an advertised ETA).

@GladosBlueWallet GladosBlueWallet left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Bugfix PR: count pendingRecovery in Arkade headline balance and block LN pays with a clearer error. Balance math tracks the SDK story; the guard is sane on ScanLNDInvoice. Your test chamber skipped the actual balance regression and several guard edge cases — classic.

Inline findings (could not anchor on diff)

  • tests/unit/lightning-ark-wallet.test.ts:1240[HIGH] You rewrote balance as total − boarding to swallow pendingRecovery, then never tested it in fetchBalance. Existing cases still pass with pendingRecovery: 0; the headline fix is theater until a wallet-full-of-recovering-sats case proves otherwise.
  • class/wallets/lightning-ark-wallet.ts:645[MEDIUM] Native Ark sendBitcoin exits before your recovering-funds guard. Wallet shows recovery-inclusive balance; user pays an ark1 address with unspendable VTXOs and gets the same cryptic failure you claimed to eliminate. One door has a warning sign; the other is a pit.

});
});

it('payInvoice blocks with a recovering-funds message when the balance is mostly pendingRecovery', async () => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[HIGH] Guard tests only cover the zero-spendable horror show. No subject verifies mixed wallets (spendable covers invoice → swap proceeds), fee-boundary blocks with _feesLoaded, or past nextSweepEta falling back. You built a safety interlock and only photographed it engaged.

// that case and surface an honest message instead.
const balance = await this._wallet.getBalance();
const spendable = balance.available + balance.recoverable;
const estFee = this.getSubmarineFeeEstimate(invoiceDetails.amountSats) ?? 0;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[MEDIUM] Guard fee math uses getSubmarineFeeEstimate(...) ?? 0 but payInvoice never calls ensureLightningFeesLoaded. ScanLNDInvoice warms fees; lnurlPay does not — mixed spendable+recovery wallets can sail past your guard and die on a generic SDK insufficient-funds error. Congratulations on a partial fix.

@Overtorment Overtorment left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

so, whats the verdict on this one? do we need it?

i see glados is not happy with the code

@GladosBlueWallet

Copy link
Copy Markdown
Collaborator

Wake the fuck up samurai, we have PRs to merge

image

[all PRs for @ncoelho] https://github.com/BlueWallet/BlueWallet/pulls/review-requested/ncoelho

1 similar comment
@GladosBlueWallet

Copy link
Copy Markdown
Collaborator

Wake the fuck up samurai, we have PRs to merge

image

[all PRs for @ncoelho] https://github.com/BlueWallet/BlueWallet/pulls/review-requested/ncoelho

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.

3 participants