mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-06-06 10:41:21 +02:00
fix(nwc): prevent pay_invoice timeout when relay is in reconnect backoff
The root cause was that WalletConnect.pool was set directly, which caused the library to use pool.subscription() and pool.publish() internally. Both methods call pool.group(relays) with ignoreOffline=true by default, which silently filters out relays whose ready state is false (i.e. relays in reconnect backoff after a momentary disconnection). This meant that when a user called payInvoice while the NWC relay was briefly reconnecting: 1. The request event was "published" to zero relays (silently dropped) 2. The response subscription was also on zero relays 3. The 30-second timeout would fire with no recovery possible The fix provides custom subscriptionMethod and publishMethod that use pool.group(relays, false) — ignoreOffline=false — which passes relays through to the underlying Relay instance. The Relay class has a proper waitForReady() mechanism that queues operations until the relay reconnects, rather than silently dropping them. Also uses WalletConnect.fromJSON() for wallet restore (idiomatic applesauce API) and removes the now-unused custom hexToBytes helper. https://claude.ai/code/session_01LNdzz2qi4hvjCzKBjTK5Gy
This commit is contained in:
@@ -20,8 +20,20 @@ import {
|
||||
import pool from "./relay-pool";
|
||||
import { BehaviorSubject, Subscription, firstValueFrom, timeout } from "rxjs";
|
||||
|
||||
// Configure the pool for wallet connect
|
||||
WalletConnect.pool = pool;
|
||||
// Configure wallet connect with custom methods that don't filter offline relays.
|
||||
//
|
||||
// By default, pool.subscription() and pool.publish() call pool.group(relays)
|
||||
// with ignoreOffline=true, which silently drops relays in reconnect backoff.
|
||||
// This causes NWC requests to be published to ZERO relays if the NWC relay
|
||||
// has a momentary disconnection, making pay_invoice appear to time out.
|
||||
//
|
||||
// Using ignoreOffline=false ensures the underlying Relay.waitForReady() is
|
||||
// used instead, which queues operations until the relay reconnects rather
|
||||
// than silently dropping them.
|
||||
WalletConnect.subscriptionMethod = (relays, filters) =>
|
||||
pool.group(relays, false).subscription(filters);
|
||||
WalletConnect.publishMethod = (relays, event) =>
|
||||
pool.group(relays, false).publish(event);
|
||||
|
||||
// Internal state
|
||||
let notificationSubscription: Subscription | null = null;
|
||||
@@ -63,14 +75,6 @@ export const transactionsState$ = new BehaviorSubject<TransactionsState>(
|
||||
// Internal helpers
|
||||
// ============================================================================
|
||||
|
||||
function hexToBytes(hex: string): Uint8Array {
|
||||
const bytes = new Uint8Array(hex.length / 2);
|
||||
for (let i = 0; i < hex.length; i += 2) {
|
||||
bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to wallet notifications with automatic retry on error.
|
||||
* Notifications trigger balance refresh for real-time updates.
|
||||
@@ -169,10 +173,10 @@ export async function restoreWallet(
|
||||
connectionStatus$.next("connecting");
|
||||
lastError$.next(null);
|
||||
|
||||
const wallet = new WalletConnect({
|
||||
const wallet = WalletConnect.fromJSON({
|
||||
service: connection.service,
|
||||
relays: connection.relays,
|
||||
secret: hexToBytes(connection.secret),
|
||||
secret: connection.secret,
|
||||
});
|
||||
|
||||
wallet$.next(wallet);
|
||||
|
||||
Reference in New Issue
Block a user