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