mirror of
https://github.com/Routstr/routstrd.git
synced 2026-08-09 03:44:38 +00:00
feat: hot-reload NWC connection (remove restart requirement)
- Add reconnect() method to wallet adapter that tears down old WalletConnect/RelayPool and creates a new one on the fly - Auto-refill loop now uses a getWallet() getter so it always references the latest wallet instance after reconnect - POST /nwc/connect and /nwc/disconnect handlers call reconnect() after saving config, no restart needed - Remove 'Run routstrd restart' messages from CLI connect/disconnect
This commit is contained in:
@@ -1319,8 +1319,6 @@ nwcCmd
|
||||
method: "POST",
|
||||
body: { connectionString },
|
||||
});
|
||||
|
||||
console.log("\nRun 'routstrd restart' to connect to the NWC wallet.");
|
||||
});
|
||||
|
||||
nwcCmd
|
||||
@@ -1330,7 +1328,6 @@ nwcCmd
|
||||
await handleDaemonCommand("/nwc/disconnect", {
|
||||
method: "POST",
|
||||
});
|
||||
console.log("\nRun 'routstrd restart' to apply.");
|
||||
});
|
||||
|
||||
nwcCmd
|
||||
|
||||
@@ -468,10 +468,12 @@ export function createDaemonRequestHandler(deps: {
|
||||
};
|
||||
saveDaemonConfig(config);
|
||||
|
||||
// Hot-reload: reconnect the wallet adapter with the new connection string
|
||||
await deps.walletAdapter.reconnect(connectionString);
|
||||
|
||||
return {
|
||||
output: {
|
||||
message:
|
||||
"NWC connection string saved. Restart the daemon to connect.",
|
||||
message: "NWC connection string saved and connected.",
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -488,8 +490,12 @@ export function createDaemonRequestHandler(deps: {
|
||||
}
|
||||
}
|
||||
saveDaemonConfig(config);
|
||||
|
||||
// Hot-reload: disconnect the wallet adapter
|
||||
await deps.walletAdapter.reconnect();
|
||||
|
||||
return {
|
||||
output: { message: "NWC disconnected. Restart the daemon to apply." },
|
||||
output: { message: "NWC disconnected." },
|
||||
};
|
||||
});
|
||||
return;
|
||||
|
||||
@@ -34,7 +34,7 @@ function isFatalError(message: string): boolean {
|
||||
|
||||
export function startAutoRefillLoop(
|
||||
cocod: CocodClient,
|
||||
wallet: WalletConnect,
|
||||
getWallet: () => WalletConnect | undefined,
|
||||
getConfig: () => AutoRefillConfig | undefined,
|
||||
intervalMs: number = 5000,
|
||||
): () => void {
|
||||
@@ -47,7 +47,8 @@ export function startAutoRefillLoop(
|
||||
async function checkAndRefill(): Promise<void> {
|
||||
if (!running) return;
|
||||
if (checkInProgress) return;
|
||||
if (!wallet.service) {
|
||||
const wallet = getWallet();
|
||||
if (!wallet?.service) {
|
||||
// NWC not connected — nothing to do
|
||||
return;
|
||||
}
|
||||
@@ -108,7 +109,12 @@ export function startAutoRefillLoop(
|
||||
|
||||
// Step 2: Pay the invoice via NWC (applesauce)
|
||||
logger.log(`[auto-refill] Paying invoice via NWC...`);
|
||||
const { preimage, fees_paid } = await wallet.payInvoice(invoice);
|
||||
const currentWallet = getWallet();
|
||||
if (!currentWallet?.service) {
|
||||
logger.log("[auto-refill] Wallet disconnected during refill check");
|
||||
return;
|
||||
}
|
||||
const { preimage, fees_paid } = await currentWallet.payInvoice(invoice);
|
||||
|
||||
// Step 3: The Cashu mint should automatically detect the paid invoice
|
||||
// and issue tokens. We don't need to explicitly mint here; cocod
|
||||
|
||||
@@ -67,6 +67,9 @@ export async function createWalletAdapter(
|
||||
let wallet: WalletConnect | undefined;
|
||||
let pool: RelayPool | undefined;
|
||||
|
||||
// Getter for the current wallet instance (used by auto-refill loop)
|
||||
const getWallet = (): WalletConnect | undefined => wallet;
|
||||
|
||||
if (options.nwcConnectionString) {
|
||||
pool = new RelayPool();
|
||||
wallet = WalletConnect.fromConnectURI(options.nwcConnectionString, { pool });
|
||||
@@ -84,6 +87,42 @@ export async function createWalletAdapter(
|
||||
}
|
||||
|
||||
const walletAdapter = {
|
||||
async reconnect(connectionString?: string): Promise<void> {
|
||||
logger.log(
|
||||
`[nwc] Reconnecting NWC wallet... ${connectionString ? "new connection string provided" : "disconnecting"}`,
|
||||
);
|
||||
|
||||
// 1. Close existing relay pool connections
|
||||
if (pool) {
|
||||
for (const [url] of pool.relays) {
|
||||
pool.remove(url, true);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Update wallet reference
|
||||
wallet = undefined;
|
||||
pool = undefined;
|
||||
|
||||
// 3. Create new wallet if connection string provided
|
||||
if (connectionString) {
|
||||
pool = new RelayPool();
|
||||
wallet = WalletConnect.fromConnectURI(connectionString, { pool });
|
||||
|
||||
// Connect in background (non-blocking)
|
||||
wallet.waitForService()
|
||||
.then(() => {
|
||||
logger.log(
|
||||
`[nwc] NWC wallet reconnected. Relay: ${wallet!.relays[0]}, Service: ${wallet!.service}`,
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
logger.error(`[nwc] NWC reconnection failed: ${err.message}`);
|
||||
});
|
||||
} else {
|
||||
logger.log("[nwc] NWC wallet disconnected.");
|
||||
}
|
||||
},
|
||||
|
||||
async getBalances(): Promise<Record<string, number>> {
|
||||
return syncMintState();
|
||||
},
|
||||
@@ -278,14 +317,14 @@ export async function createWalletAdapter(
|
||||
|
||||
if (autoRefillConfig && wallet) {
|
||||
const getConfig = options.getAutoRefillConfig ?? (() => options.autoRefill);
|
||||
stopAutoRefill = startAutoRefillLoop(client, wallet, getConfig);
|
||||
stopAutoRefill = startAutoRefillLoop(client, getWallet, getConfig);
|
||||
logger.log(
|
||||
`[wallet] Auto-refill enabled: threshold=${autoRefillConfig.threshold} sats, amount=${autoRefillConfig.amount} sats, cooldown=${autoRefillConfig.cooldownMs}ms`,
|
||||
);
|
||||
} else if (wallet && options.getAutoRefillConfig) {
|
||||
// Wallet exists but auto-refill is not currently enabled.
|
||||
// Start the loop anyway so it can pick up changes without a restart.
|
||||
stopAutoRefill = startAutoRefillLoop(client, wallet, options.getAutoRefillConfig);
|
||||
stopAutoRefill = startAutoRefillLoop(client, getWallet, options.getAutoRefillConfig);
|
||||
logger.log("[wallet] Auto-refill loop started (currently disabled — enable via CLI to activate)");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user