Merge pull request 'fix(wallet): refetch balance and history on resume' (#164) from fix/wallet-resume-refetch into dev
Reviewed-on: #164
This commit is contained in:
commit
586698259a
1 changed files with 72 additions and 34 deletions
|
|
@ -437,6 +437,39 @@ export class WalletWebSocketService extends BaseService {
|
||||||
// Resume polling if we were using fallback
|
// Resume polling if we were using fallback
|
||||||
this.schedulePolling()
|
this.schedulePolling()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reconnecting is not enough on its own — see below.
|
||||||
|
await this.reconcileMissedActivity()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-sync balance and history after the app was backgrounded.
|
||||||
|
*
|
||||||
|
* `onPause` closes the socket to save battery, and the LNbits websocket
|
||||||
|
* only pushes on live events — it replays nothing on reconnect. So any
|
||||||
|
* payment that settled while we were away produced a notification that
|
||||||
|
* reached no one: the balance and the transaction list both stayed at
|
||||||
|
* their pre-pause values until the user hit Refresh by hand.
|
||||||
|
*
|
||||||
|
* Reconnecting therefore has to be paired with an explicit refetch. Both
|
||||||
|
* halves are needed: the balance comes from PaymentService, the rows come
|
||||||
|
* from WalletService, and neither implies the other.
|
||||||
|
*
|
||||||
|
* `allSettled` so a failure in one does not leave the other un-refreshed.
|
||||||
|
*/
|
||||||
|
private async reconcileMissedActivity(): Promise<void> {
|
||||||
|
console.log('WalletWebSocketService: Reconciling activity missed while paused')
|
||||||
|
|
||||||
|
const results = await Promise.allSettled([
|
||||||
|
this.fetchAndUpdateBalance(),
|
||||||
|
this.walletService?.refresh?.()
|
||||||
|
])
|
||||||
|
|
||||||
|
results
|
||||||
|
.filter((r): r is PromiseRejectedResult => r.status === 'rejected')
|
||||||
|
.forEach(r =>
|
||||||
|
console.error('WalletWebSocketService: Resume reconciliation failed', r.reason)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -556,14 +589,27 @@ export class WalletWebSocketService extends BaseService {
|
||||||
*/
|
*/
|
||||||
private async performPollingUpdate(): Promise<void> {
|
private async performPollingUpdate(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
|
await this.fetchAndUpdateBalance()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('WalletWebSocketService: Polling error', error)
|
||||||
|
} finally {
|
||||||
|
// Keep polling regardless of the outcome of this round.
|
||||||
|
this.schedulePolling()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the authoritative wallet balance from LNbits and push it into
|
||||||
|
* PaymentService. Shared by the polling fallback and by resume
|
||||||
|
* reconciliation.
|
||||||
|
*/
|
||||||
|
private async fetchAndUpdateBalance(): Promise<void> {
|
||||||
const wallet = this.paymentService?.getPreferredWallet?.()
|
const wallet = this.paymentService?.getPreferredWallet?.()
|
||||||
if (!wallet?.inkey) {
|
if (!wallet?.inkey) {
|
||||||
console.log('WalletWebSocketService: No wallet available for polling')
|
console.log('WalletWebSocketService: No wallet available for balance fetch')
|
||||||
this.schedulePolling() // Continue polling
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch balance from LNbits API
|
|
||||||
const baseUrl = import.meta.env.VITE_LNBITS_BASE_URL || 'http://localhost:5000'
|
const baseUrl = import.meta.env.VITE_LNBITS_BASE_URL || 'http://localhost:5000'
|
||||||
const response = await fetch(`${baseUrl}/api/v1/wallet`, {
|
const response = await fetch(`${baseUrl}/api/v1/wallet`, {
|
||||||
headers: {
|
headers: {
|
||||||
|
|
@ -572,31 +618,23 @@ export class WalletWebSocketService extends BaseService {
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
console.error('WalletWebSocketService: Polling failed', response.status, response.statusText)
|
console.error(
|
||||||
this.schedulePolling() // Continue polling despite error
|
'WalletWebSocketService: Balance fetch failed',
|
||||||
|
response.status,
|
||||||
|
response.statusText
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
|
|
||||||
if (data.balance !== undefined) {
|
if (data.balance !== undefined) {
|
||||||
// LNbits API returns balance in millisats
|
// LNbits API returns balance in millisats
|
||||||
const balanceMsat = parseInt(data.balance)
|
const balanceMsat = parseInt(data.balance)
|
||||||
console.log('WalletWebSocketService: Polling update - balance:', balanceMsat, 'msat')
|
console.log('WalletWebSocketService: Balance fetch -', balanceMsat, 'msat')
|
||||||
|
|
||||||
// Update balance via PaymentService
|
|
||||||
if (this.paymentService?.updateWalletBalance) {
|
if (this.paymentService?.updateWalletBalance) {
|
||||||
this.paymentService.updateWalletBalance(balanceMsat, wallet.id)
|
this.paymentService.updateWalletBalance(balanceMsat, wallet.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schedule next polling
|
|
||||||
this.schedulePolling()
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('WalletWebSocketService: Polling error', error)
|
|
||||||
this.schedulePolling() // Continue polling despite error
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue