diff --git a/src/commands/auth.ts b/src/commands/auth.ts index f8b5547..b5d0da3 100644 --- a/src/commands/auth.ts +++ b/src/commands/auth.ts @@ -4,6 +4,7 @@ import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs"; import { homedir } from "node:os"; import { join } from "node:path"; import { + DEFAULT_RELAY_URLS, getConnectionSecretPath, getPendingConnectionRelayPath, getPendingConnectionSecretPath, @@ -28,8 +29,9 @@ export function registerAuthCommand(program: Command) { ) .option( "--relay-url ", - "Relay URL for the pending connection", - "wss://relay.getalby.com/v1", + `Relay URL for the pending connection (repeat to use multiple relays, default: ${DEFAULT_RELAY_URLS.join(", ")})`, + (value: string, previous: string[]) => previous.concat([value]), + [] as string[], ) .option("--force", "Overwrite existing connection secret") .option("--remove-pending", "Remove a pending connection and start fresh") @@ -39,7 +41,7 @@ export function registerAuthCommand(program: Command) { options: { appName?: string; force?: boolean; - relayUrl: string; + relayUrl: string[]; removePending?: boolean; }, ) => { @@ -83,6 +85,11 @@ export function registerAuthCommand(program: Command) { process.exit(1); } + const relayUrls = + options.relayUrl.length > 0 + ? options.relayUrl + : DEFAULT_RELAY_URLS; + const secret = bytesToHex(generateSecretKey()); const pubkey = getPublicKey(hexToBytes(secret)); @@ -97,7 +104,11 @@ export function registerAuthCommand(program: Command) { mkdirSync(dir, { recursive: true }); } writeFileSync(pendingSecretPath, secret, { mode: 0o600 }); - writeFileSync(pendingRelayPath, options.relayUrl, { mode: 0o600 }); + // Store one relay per line so multiple relays survive the + // round-trip to the completion step. + writeFileSync(pendingRelayPath, relayUrls.join("\n"), { + mode: 0o600, + }); console.log( "Click the following URL to approve the connection in your wallet:\n" + diff --git a/src/utils.ts b/src/utils.ts index 3ddc15e..a87f706 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -12,6 +12,11 @@ import { import { homedir } from "node:os"; import { join } from "node:path"; +export const DEFAULT_RELAY_URLS = [ + "wss://relay.getalby.com", + "wss://relay2.getalby.com", +]; + function sanitizeWalletName(name: string): string { return name.replace(/[^a-zA-Z0-9_-]/g, "_"); } @@ -67,21 +72,28 @@ export async function testAndLogConnection(client: NWCClient) { export async function completePendingConnection( pendingSecretPath: string, connectionSecretPath: string, - relayUrl: string | undefined, + relayUrls: string[] | undefined, verbose: boolean, pendingRelayPath?: string, ): Promise { const secret = readFileSync(pendingSecretPath, "utf-8").trim(); - const DEFAULT_RELAY = "wss://relay.getalby.com/v1"; - if (!relayUrl && pendingRelayPath && existsSync(pendingRelayPath)) { - relayUrl = readFileSync(pendingRelayPath, "utf-8").trim(); + if ( + (!relayUrls || relayUrls.length === 0) && + pendingRelayPath && + existsSync(pendingRelayPath) + ) { + relayUrls = readFileSync(pendingRelayPath, "utf-8") + .split("\n") + .map((line) => line.trim()) + .filter((line) => line.length > 0); } - const resolvedRelay = relayUrl ?? DEFAULT_RELAY; + const resolvedRelays = + relayUrls && relayUrls.length > 0 ? relayUrls : DEFAULT_RELAY_URLS; const nwaClient = new NWAClient({ appSecretKey: secret, - relayUrls: [resolvedRelay], + relayUrls: resolvedRelays, requestMethods: [], });