fix: improve reliability of NWC service by isolating its pool

This commit is contained in:
Alejandro Gómez
2026-03-02 09:38:29 +01:00
parent 53add37fab
commit 5c1d7c0c63
2 changed files with 22 additions and 21 deletions

View File

@@ -11,7 +11,7 @@
* - Shows feed render of zapped event
*/
import { useState, useMemo, useEffect, useRef } from "react";
import { useState, useMemo, useRef } from "react";
import { toast } from "sonner";
import {
Zap,
@@ -118,17 +118,7 @@ export function ZapWindow({
const activeAccount = accountManager.active;
const canSign = !!activeAccount?.signer;
const { wallet, payInvoice, refreshBalance, getInfo } = useWallet();
// Fetch wallet info
const [walletInfo, setWalletInfo] = useState<any>(null);
useEffect(() => {
if (wallet) {
getInfo()
.then((info) => setWalletInfo(info))
.catch((error) => console.error("Failed to get wallet info:", error));
}
}, [wallet, getInfo]);
const { wallet, payInvoice, refreshBalance, walletMethods } = useWallet();
// Cache LNURL data for recipient's Lightning address
const { data: lnurlData } = useLnurlCache(recipientProfile?.lud16);
@@ -399,7 +389,7 @@ export function ZapWindow({
setInvoice(invoiceText);
// Step 5: Pay or show QR code
if (useWallet && wallet && walletInfo?.methods.includes("pay_invoice")) {
if (useWallet && wallet && walletMethods.includes("pay_invoice")) {
// Pay with NWC wallet with timeout
setIsPayingWithWallet(true);
try {
@@ -567,7 +557,7 @@ export function ZapWindow({
{/* Retry with wallet button if payment failed/timed out */}
{paymentTimedOut &&
wallet &&
walletInfo?.methods.includes("pay_invoice") && (
walletMethods.includes("pay_invoice") && (
<Button
onClick={handleRetryWallet}
disabled={isProcessing}
@@ -667,7 +657,7 @@ export function ZapWindow({
placeholder="Say something nice..."
searchProfiles={searchProfiles}
searchEmojis={searchEmojis}
className="rounded-md border border-input bg-background px-3 py-1 text-base md:text-sm min-h-9"
className="w-full"
/>
)}
@@ -717,7 +707,7 @@ export function ZapWindow({
isPaid
? onClose?.()
: handleZap(
wallet && walletInfo?.methods.includes("pay_invoice"),
!!(wallet && walletMethods.includes("pay_invoice")),
)
}
disabled={
@@ -740,7 +730,7 @@ export function ZapWindow({
<CheckCircle2 className="size-4 mr-2" />
Done
</>
) : wallet && walletInfo?.methods.includes("pay_invoice") ? (
) : wallet && walletMethods.includes("pay_invoice") ? (
<>
<Wallet className="size-4 mr-2" />
Pay with Wallet (

View File

@@ -12,20 +12,24 @@
*/
import { WalletConnect } from "applesauce-wallet-connect";
import { RelayPool } from "applesauce-relay";
import type { NWCConnection } from "@/types/app";
import {
type TransactionsState,
INITIAL_TRANSACTIONS_STATE,
} from "@/types/wallet";
import pool from "./relay-pool";
import { BehaviorSubject, Subscription, firstValueFrom, timeout } from "rxjs";
// Configure the pool for wallet connect
WalletConnect.pool = pool;
// Dedicated relay pool for NWC — isolated from the shared app pool and relay
// liveness tracking, which can deprioritize or skip the wallet relay
const nwcPool = new RelayPool();
WalletConnect.pool = nwcPool;
// Internal state
let notificationSubscription: Subscription | null = null;
let notificationRetryTimeout: ReturnType<typeof setTimeout> | null = null;
/** Persistent support$ subscription — keeps events$ relay subscription alive */
let supportSubscription: Subscription | null = null;
/**
* Connection status for the NWC wallet
@@ -153,6 +157,8 @@ export function createWalletFromURI(connectionString: string): WalletConnect {
const wallet = WalletConnect.fromConnectURI(connectionString);
wallet$.next(wallet);
supportSubscription?.unsubscribe();
supportSubscription = wallet.support$.subscribe();
subscribeToNotifications(wallet);
refreshBalance(); // Fetch initial balance
@@ -177,6 +183,9 @@ export async function restoreWallet(
wallet$.next(wallet);
supportSubscription?.unsubscribe();
supportSubscription = wallet.support$.subscribe();
// Show cached balance immediately while validating
if (connection.balance !== undefined) {
balance$.next(connection.balance);
@@ -214,7 +223,9 @@ export async function restoreWallet(
* Disconnects and clears the wallet.
*/
export function clearWallet(): void {
// Clean up subscription and pending retry
// Clean up subscriptions and pending retry
supportSubscription?.unsubscribe();
supportSubscription = null;
notificationSubscription?.unsubscribe();
notificationSubscription = null;
if (notificationRetryTimeout) {