-
Notifications
You must be signed in to change notification settings - Fork 2
fix: handle dust change in max transfer to spending #748
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment was marked as resolved.
This comment was marked as resolved.
…spendableBalance to calculate the txFee
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added 2 nits and a request for change; pls don't use something1 and something2 naming 🙏🏻
| val address = order.payment?.onchain?.address.orEmpty() | ||
|
|
||
| // Calculate if change would be dust and we should use sendAll | ||
| val spendableBalance = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can be extracted to a private method
| // Two-pass fee estimation to match actual order creation | ||
| // First pass: estimate with availableAmount to get approximate clientBalance | ||
| val values1 = blocktankRepo.calculateLiquidityOptions(availableAmount).getOrNull() | ||
| if (values1 == null) { | ||
| _spendingUiState.update { it.copy(isLoading = false) } | ||
| return@launch | ||
| } | ||
| val lspBalance1 = maxOf(values1.defaultLspBalanceSat, values1.minLspBalanceSat) | ||
| val feeEstimate1 = blocktankRepo.estimateOrderFee( | ||
| spendingBalanceSats = availableAmount, | ||
| receivingBalanceSats = _transferValues.value.maxLspBalance | ||
| receivingBalanceSats = lspBalance1, | ||
| ).getOrNull() | ||
|
|
||
| if (feeEstimate1 == null) { | ||
| _spendingUiState.update { it.copy(isLoading = false) } | ||
| return@launch | ||
| } | ||
|
|
||
| val lspFees1 = feeEstimate1.networkFeeSat.safe() + feeEstimate1.serviceFeeSat.safe() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can also be extracted to a method
| val values2 = blocktankRepo.calculateLiquidityOptions(approxClientBalance).getOrNull() | ||
| if (values2 == null || values2.maxLspBalanceSat == 0uL) { | ||
| _spendingUiState.update { it.copy(isLoading = false, maxAllowedToSend = 0) } | ||
| return@launch | ||
| } | ||
| val lspBalance2 = maxOf(values2.defaultLspBalanceSat, values2.minLspBalanceSat) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
values1/ values2 is not descriptive enough; makes reader have to actually read implementation to understand what it means
Fixes #745
This PR fixes the "insufficient funds" error that occurs when transferring the maximum balance to spending.
Description
When users tried to transfer their full on-chain balance to Lightning (spending), they would sometimes encounter an "insufficient funds" error even though they had enough sats. This happened because:
Fee estimation mismatch - The LSP fee was estimated using
maxSendableamount, but order creation uses a differentclientBalancevalue. SincelspBalancedepends onclientBalanceSat, this caused off-by-few-sats discrepancies.Dust change handling - When the remaining change after the transfer would be below the dust limit (546 sats), the transaction would fail because Bitcoin nodes reject dust outputs.
Changes:
sendAllwhen remaining change would be below dust limitReference: iOS fix PR #416
Preview
Screen_recording_20260129_085609.webm
not-dust.webm
QA Notes
1. MAX transfer to spending
2. Near-dust change scenarios
sendAllis used (no dust output created)3. Regression - Partial transfers