{"ast":null,"code":"import _asyncToGenerator from \"/home/mleku/src/orly.dev/next/signer/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js\";\n/**\n * NIP-42 Relay Authentication\n *\n * Handles WebSocket connections to relays that require authentication.\n * When a relay sends an AUTH challenge, this module signs the challenge\n * and authenticates before proceeding with event publishing.\n */\nimport { finalizeEvent, getPublicKey } from 'nostr-tools';\n/**\n * Create a NIP-42 authentication event (kind 22242)\n */\nfunction createAuthEvent(relayUrl, challenge, privateKeyHex) {\n  const unsignedEvent = {\n    kind: 22242,\n    created_at: Math.floor(Date.now() / 1000),\n    tags: [['relay', relayUrl], ['challenge', challenge]],\n    content: ''\n  };\n  // Convert hex private key to Uint8Array\n  const privkeyBytes = hexToBytes(privateKeyHex);\n  return finalizeEvent(unsignedEvent, privkeyBytes);\n}\n/**\n * Convert hex string to Uint8Array\n */\nfunction hexToBytes(hex) {\n  const bytes = new Uint8Array(hex.length / 2);\n  for (let i = 0; i < bytes.length; i++) {\n    bytes[i] = parseInt(hex.substr(i * 2, 2), 16);\n  }\n  return bytes;\n}\n/**\n * Connect to a relay with NIP-42 authentication support\n *\n * @param relayUrl - The relay WebSocket URL (e.g., wss://relay.example.com)\n * @param privateKeyHex - The private key in hex format for signing\n * @param timeoutMs - Connection and authentication timeout in milliseconds\n * @returns Promise resolving to authenticated connection or null if failed\n */\nexport function connectWithAuth(_x, _x2) {\n  return _connectWithAuth.apply(this, arguments);\n}\n/**\n * Publish an event to a relay with NIP-42 authentication support\n *\n * This function handles the complete flow:\n * 1. Connect to relay\n * 2. Handle AUTH challenge if sent\n * 3. Publish the event\n * 4. Wait for OK response\n * 5. Close connection\n *\n * @param relayUrl - The relay WebSocket URL\n * @param signedEvent - The already-signed Nostr event to publish\n * @param privateKeyHex - Private key for AUTH (if required)\n * @param timeoutMs - Timeout for the entire operation\n * @returns Promise resolving to publish result\n */\nfunction _connectWithAuth() {\n  _connectWithAuth = _asyncToGenerator(function* (relayUrl, privateKeyHex, timeoutMs = 10000) {\n    return new Promise(resolve => {\n      const timeout = setTimeout(() => {\n        ws.close();\n        resolve(null);\n      }, timeoutMs);\n      const ws = new WebSocket(relayUrl);\n      const pubkey = getPublicKey(hexToBytes(privateKeyHex));\n      ws.onopen = () => {\n        // Connection open, wait for AUTH challenge or proceed directly\n      };\n      ws.onmessage = event => {\n        try {\n          const message = JSON.parse(event.data);\n          const messageType = message[0];\n          if (messageType === 'AUTH') {\n            // Relay sent an auth challenge\n            const challenge = message[1];\n            const authEvent = createAuthEvent(relayUrl, challenge, privateKeyHex);\n            // Send AUTH response\n            ws.send(JSON.stringify(['AUTH', authEvent]));\n          } else if (messageType === 'OK') {\n            // Check if this is the AUTH response\n            const success = message[2];\n            const msg = message[3] || '';\n            if (success) {\n              clearTimeout(timeout);\n              resolve({\n                ws,\n                url: relayUrl,\n                authenticated: true,\n                pubkey\n              });\n            } else {\n              console.error(`Auth failed for ${relayUrl}: ${msg}`);\n              clearTimeout(timeout);\n              ws.close();\n              resolve(null);\n            }\n          } else if (messageType === 'NOTICE') {\n            // Some relays don't require auth - connection is ready\n            clearTimeout(timeout);\n            resolve({\n              ws,\n              url: relayUrl,\n              authenticated: false,\n              pubkey\n            });\n          }\n        } catch {\n          // Ignore parse errors\n        }\n      };\n      ws.onerror = () => {\n        clearTimeout(timeout);\n        resolve(null);\n      };\n      ws.onclose = () => {\n        clearTimeout(timeout);\n      };\n      // For relays that don't send AUTH challenge, resolve after short delay\n      setTimeout(() => {\n        if (ws.readyState === WebSocket.OPEN) {\n          clearTimeout(timeout);\n          resolve({\n            ws,\n            url: relayUrl,\n            authenticated: false,\n            // No auth was required\n            pubkey\n          });\n        }\n      }, 2000); // Wait 2 seconds for potential AUTH challenge\n    });\n  });\n  return _connectWithAuth.apply(this, arguments);\n}\nexport function publishEventWithAuth(_x3, _x4, _x5) {\n  return _publishEventWithAuth.apply(this, arguments);\n}\n/**\n * Publish an event to multiple relays with NIP-42 support\n *\n * @param relayUrls - Array of relay WebSocket URLs\n * @param signedEvent - The already-signed Nostr event to publish\n * @param privateKeyHex - Private key for AUTH (if required)\n * @returns Promise resolving to array of publish results\n */\nfunction _publishEventWithAuth() {\n  _publishEventWithAuth = _asyncToGenerator(function* (relayUrl, signedEvent, privateKeyHex, timeoutMs = 15000) {\n    return new Promise(resolve => {\n      const timeout = setTimeout(() => {\n        if (ws && ws.readyState === WebSocket.OPEN) {\n          ws.close();\n        }\n        resolve({\n          relay: relayUrl,\n          success: false,\n          message: 'Timeout'\n        });\n      }, timeoutMs);\n      let ws;\n      let authenticated = false;\n      let eventSent = false;\n      try {\n        ws = new WebSocket(relayUrl);\n      } catch (e) {\n        clearTimeout(timeout);\n        resolve({\n          relay: relayUrl,\n          success: false,\n          message: `Connection failed: ${e}`\n        });\n        return;\n      }\n      const sendEvent = () => {\n        if (!eventSent && ws.readyState === WebSocket.OPEN) {\n          eventSent = true;\n          ws.send(JSON.stringify(['EVENT', signedEvent]));\n        }\n      };\n      ws.onopen = () => {\n        // Wait a moment for potential AUTH challenge before sending event\n        setTimeout(() => {\n          if (!authenticated) {\n            // No auth challenge received, try sending event directly\n            sendEvent();\n          }\n        }, 500);\n      };\n      ws.onmessage = event => {\n        try {\n          const message = JSON.parse(event.data);\n          const messageType = message[0];\n          if (messageType === 'AUTH') {\n            // Relay requires authentication\n            const challenge = message[1];\n            const authEvent = createAuthEvent(relayUrl, challenge, privateKeyHex);\n            ws.send(JSON.stringify(['AUTH', authEvent]));\n            authenticated = true;\n          } else if (messageType === 'OK') {\n            const eventId = message[1];\n            const success = message[2];\n            const msg = message[3] || '';\n            // Check if this is our event or AUTH response\n            if (eventId === signedEvent.id) {\n              // This is the response to our published event\n              clearTimeout(timeout);\n              ws.close();\n              if (success) {\n                resolve({\n                  relay: relayUrl,\n                  success: true,\n                  message: 'Published successfully'\n                });\n              } else {\n                // Check if we need to retry after auth\n                if (msg.includes('auth-required') && !authenticated) {\n                  // Relay requires auth but didn't send challenge\n                  // This shouldn't normally happen\n                  resolve({\n                    relay: relayUrl,\n                    success: false,\n                    message: 'Auth required but no challenge received'\n                  });\n                } else {\n                  resolve({\n                    relay: relayUrl,\n                    success: false,\n                    message: msg || 'Publish rejected'\n                  });\n                }\n              }\n            } else if (authenticated && !eventSent) {\n              // This is the OK response to our AUTH\n              if (success) {\n                // Auth succeeded, now send the event\n                sendEvent();\n              } else {\n                clearTimeout(timeout);\n                ws.close();\n                resolve({\n                  relay: relayUrl,\n                  success: false,\n                  message: `Authentication failed: ${msg}`\n                });\n              }\n            }\n          } else if (messageType === 'NOTICE') {\n            // Log notices but don't fail\n            console.log(`Relay ${relayUrl} notice: ${message[1]}`);\n          }\n        } catch {\n          // Ignore parse errors\n        }\n      };\n      ws.onerror = () => {\n        clearTimeout(timeout);\n        resolve({\n          relay: relayUrl,\n          success: false,\n          message: 'Connection error'\n        });\n      };\n      ws.onclose = () => {\n        // If we haven't resolved yet, treat as failure\n        clearTimeout(timeout);\n      };\n    });\n  });\n  return _publishEventWithAuth.apply(this, arguments);\n}\nexport function publishToRelaysWithAuth(_x6, _x7, _x8) {\n  return _publishToRelaysWithAuth.apply(this, arguments);\n}\nfunction _publishToRelaysWithAuth() {\n  _publishToRelaysWithAuth = _asyncToGenerator(function* (relayUrls, signedEvent, privateKeyHex) {\n    const results = yield Promise.all(relayUrls.map(url => publishEventWithAuth(url, signedEvent, privateKeyHex)));\n    return results;\n  });\n  return _publishToRelaysWithAuth.apply(this, arguments);\n}","map":null,"metadata":{},"sourceType":"module","externalDependencies":[]}