fix: get balance from websocket instead of separate api call
This commit is contained in:
@@ -259,6 +259,7 @@ data class PaymentDetailResponse(
|
||||
|
||||
// ── WebSocket payment message ─────────────────────────────────────────────────
|
||||
data class WsPaymentMessage(
|
||||
@SerializedName("wallet_balance") val walletBalance: Long?,
|
||||
val payment: WsPayment?
|
||||
)
|
||||
|
||||
|
||||
+3
-1
@@ -81,6 +81,7 @@ class WalletNotificationService : Service() {
|
||||
* Emitted to [paymentEvents] for in-process UI updates.
|
||||
*/
|
||||
data class PaymentEvent(
|
||||
val walletBalance: Long?,
|
||||
val amountSats: Long,
|
||||
val memo: String?,
|
||||
val isOutgoing: Boolean,
|
||||
@@ -229,6 +230,7 @@ class WalletNotificationService : Service() {
|
||||
serviceScope.launch {
|
||||
_paymentEvents.emit(
|
||||
PaymentEvent(
|
||||
walletBalance = msg.walletBalance,
|
||||
amountSats = amountSats,
|
||||
memo = payment.memo,
|
||||
isOutgoing = isOutgoing,
|
||||
@@ -245,7 +247,7 @@ class WalletNotificationService : Service() {
|
||||
checkingId = payment.checkingId,
|
||||
paymentHash = payment.paymentHash,
|
||||
amountMsat = payment.amount,
|
||||
feeMsat = 0L, // WsPaymentMessage doesn't carry fee
|
||||
feeMsat = payment.fee,
|
||||
memo = payment.memo,
|
||||
time = payment.time,
|
||||
status = payment.status,
|
||||
|
||||
@@ -25,7 +25,7 @@ class BalanceViewModel(
|
||||
val balanceState: StateFlow<BalanceState> = _balanceState
|
||||
|
||||
// Emits after every successful balance refresh so other ViewModels
|
||||
// (e.g. FiatViewModel) can react without polling.
|
||||
// can react without polling.
|
||||
private val _balanceRefreshed = MutableSharedFlow<Long>(extraBufferCapacity = 1)
|
||||
|
||||
// Emits incoming payment events so ReceiveViewModel can update its state.
|
||||
@@ -117,25 +117,38 @@ class BalanceViewModel(
|
||||
WalletNotificationService.paymentEvents.collect { event ->
|
||||
Log.d(TAG, "BALANCE [WS EVENT ] ${if (event.isOutgoing) "SENT" else "RECEIVED"} ${event.amountSats} sats")
|
||||
|
||||
val current = _balanceState.value
|
||||
if (current is BalanceState.Success) {
|
||||
val delta = if (event.isOutgoing) -event.amountSats else event.amountSats
|
||||
val newSats = (current.sats + delta).coerceAtLeast(0L)
|
||||
Log.d(TAG, "BALANCE [WS DELTA ] ${current.sats} ${if (delta >= 0) "+" else ""}$delta = $newSats sats (optimistic)")
|
||||
_balanceState.value = current.copy(sats = newSats, isRefreshing = true)
|
||||
persistBalance(newSats)
|
||||
val newSats = if (event.walletBalance != null) {
|
||||
// Authoritative balance from the server — no delta math needed
|
||||
Log.d(TAG, "BALANCE [WS BALANCE] ${event.walletBalance} sats (from server)")
|
||||
event.walletBalance
|
||||
} else {
|
||||
Log.w(TAG, "BALANCE [WS EVENT ] Received event but balance state is ${current::class.simpleName} — skipping delta")
|
||||
// Fallback: server didn't send balance, apply delta optimistically
|
||||
val current = _balanceState.value
|
||||
if (current is BalanceState.Success) {
|
||||
val delta = if (event.isOutgoing) -event.amountSats else event.amountSats
|
||||
val sats = (current.sats + delta).coerceAtLeast(0L)
|
||||
Log.d(TAG, "BALANCE [WS DELTA ] ${current.sats} ${if (delta >= 0) "+" else ""}$delta = $sats sats (optimistic fallback)")
|
||||
sats
|
||||
} else null
|
||||
}
|
||||
|
||||
refreshBalance()
|
||||
if (newSats != null) {
|
||||
val now = System.currentTimeMillis()
|
||||
_balanceState.value = BalanceState.Success(
|
||||
sats = newSats,
|
||||
isRefreshing = false,
|
||||
lastUpdated = now
|
||||
)
|
||||
persistBalance(newSats)
|
||||
_balanceRefreshed.tryEmit(newSats)
|
||||
onBalanceRefreshed?.invoke()
|
||||
}
|
||||
|
||||
// refreshBalance() call removed — balance is authoritative from WS
|
||||
|
||||
if (!event.isOutgoing) {
|
||||
_incomingPayment.tryEmit(
|
||||
IncomingPaymentEvent(
|
||||
amountSats = event.amountSats,
|
||||
memo = event.memo
|
||||
)
|
||||
IncomingPaymentEvent(amountSats = event.amountSats, memo = event.memo)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user