96201bacbb14475f0cd70c9573b0f251953ecc03cc261c53e36c7f31f55a1cd6.json raw
1 {"ast":null,"code":"import _asyncToGenerator from \"/home/mleku/src/orly.dev/next/signer/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js\";\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { backgroundLogNip07Action, backgroundLogPermissionStored, NostrHelper, NwcClient } from '@common';\nimport { checkPermissions, checkWeblnPermissions, debug, getBrowserSessionData, getPosition, handleUnlockRequest, isWeblnMethod, nip04Decrypt, nip04Encrypt, nip44Decrypt, nip44Encrypt, openUnlockPopup, shouldRecklessModeApprove, signEvent, storePermission } from './background-common';\nimport { isMlsMethod, mlsInit, mlsSendDM, mlsSubscribe, mlsPublishKP, mlsListGroups, mlsDeliverEvent, mlsSetTab } from './mls-engine';\nimport browser from 'webextension-polyfill';\nimport { Buffer } from 'buffer';\n// Clear stale session data on extension install/update/reload.\n// Session storage can survive reloads in Firefox, causing the vault\n// to appear unlocked without the user entering their password.\nbrowser.runtime.onInstalled.addListener(/*#__PURE__*/_asyncToGenerator(function* () {\n debug('Extension installed/updated — clearing session storage');\n yield browser.storage.session.clear();\n}));\n// Cache for NWC clients to avoid reconnecting for each request\nconst nwcClientCache = new Map();\n/**\n * Get or create an NWC client for a connection\n */\nfunction getNwcClient(_x) {\n return _getNwcClient.apply(this, arguments);\n}\n/**\n * Parse invoice amount from a BOLT11 invoice string\n * Returns amount in satoshis, or undefined if no amount specified\n */\nfunction _getNwcClient() {\n _getNwcClient = _asyncToGenerator(function* (connection) {\n const cached = nwcClientCache.get(connection.id);\n if (cached && cached.isConnected()) {\n return cached;\n }\n const client = new NwcClient({\n walletPubkey: connection.walletPubkey,\n relayUrl: connection.relayUrl,\n secret: connection.secret\n });\n yield client.connect();\n nwcClientCache.set(connection.id, client);\n return client;\n });\n return _getNwcClient.apply(this, arguments);\n}\nfunction parseInvoiceAmount(invoice) {\n try {\n // BOLT11 invoices start with 'ln' followed by network prefix and amount\n // Format: ln[network][amount][multiplier]1[data]\n // Examples: lnbc1500n1... (1500 sat), lnbc1m1... (0.001 BTC = 100000 sat)\n const match = invoice.toLowerCase().match(/^ln(bc|tb|tbs|bcrt)(\\d+)([munp])?1/);\n if (!match) {\n return undefined;\n }\n const amountStr = match[2];\n const multiplier = match[3];\n let amount = parseInt(amountStr, 10);\n // Apply multiplier (amount is in BTC by default)\n switch (multiplier) {\n case 'm':\n // milli-bitcoin (0.001 BTC)\n amount = amount * 100000;\n break;\n case 'u':\n // micro-bitcoin (0.000001 BTC)\n amount = amount * 100;\n break;\n case 'n':\n // nano-bitcoin (0.000000001 BTC) = 0.1 sat\n amount = Math.floor(amount / 10);\n break;\n case 'p':\n // pico-bitcoin (0.000000000001 BTC) = 0.0001 sat\n amount = Math.floor(amount / 10000);\n break;\n default:\n // No multiplier means BTC\n amount = amount * 100000000;\n }\n return amount;\n } catch {\n return undefined;\n }\n}\n// ==========================================\n// Permission Prompt Queue System (P0)\n// ==========================================\n// Timeout for permission prompts (30 seconds)\nconst PROMPT_TIMEOUT_MS = 30000;\n// Maximum number of queued permission requests (prevent DoS)\nconst MAX_PERMISSION_QUEUE_SIZE = 100;\n// Track open prompts with metadata for cleanup\nconst openPrompts = new Map();\n// Track if unlock popup is already open\nlet unlockPopupOpen = false;\nlet unlockPopupWindowId;\n// Queue of pending NIP-07 requests waiting for unlock\nconst pendingRequests = [];\nconst permissionQueue = [];\nlet activePromptId = null;\n/**\n * Show the next permission prompt from the queue.\n * Re-checks permissions before opening — if a prior \"always\" response\n * already covers this request, auto-resolve it and skip to the next.\n */\nfunction showNextPermissionPrompt() {\n return _showNextPermissionPrompt.apply(this, arguments);\n}\n/**\n * Check if a queued prompt's request is already covered by a stored permission.\n * Returns true (allowed), false (denied), or undefined (no stored permission).\n */\nfunction _showNextPermissionPrompt() {\n _showNextPermissionPrompt = _asyncToGenerator(function* () {\n while (!activePromptId && permissionQueue.length > 0) {\n const next = permissionQueue[0];\n // Re-check: a prior \"always\" may already cover this queued request.\n const covered = yield isQueuedRequestCovered(next);\n if (covered !== undefined) {\n // Auto-resolve without opening a window.\n permissionQueue.shift();\n const promptData = openPrompts.get(next.id);\n if (promptData) {\n if (promptData.timeoutId) clearTimeout(promptData.timeoutId);\n promptData.resolve(covered ? 'approve-once' : 'reject-once');\n openPrompts.delete(next.id);\n }\n debug(`Auto-resolved queued prompt ${next.id} (permission already ${covered ? 'allowed' : 'denied'})`);\n continue; // check next item\n }\n // No stored permission — show the prompt window.\n activePromptId = next.id;\n const {\n top,\n left\n } = yield getPosition(next.width, next.height);\n try {\n const window = yield browser.windows.create({\n type: 'popup',\n url: next.url,\n height: next.height,\n width: next.width,\n top,\n left\n });\n const promptData = openPrompts.get(next.id);\n if (promptData && window.id) {\n promptData.windowId = window.id;\n promptData.timeoutId = setTimeout(() => {\n debug(`Prompt ${next.id} timed out after ${PROMPT_TIMEOUT_MS}ms`);\n cleanupPrompt(next.id, 'timeout');\n }, PROMPT_TIMEOUT_MS);\n }\n } catch (error) {\n debug(`Failed to create prompt window: ${error}`);\n cleanupPrompt(next.id, 'error');\n }\n break; // only open one prompt at a time\n }\n });\n return _showNextPermissionPrompt.apply(this, arguments);\n}\nfunction isQueuedRequestCovered(_x2) {\n return _isQueuedRequestCovered.apply(this, arguments);\n}\n/**\n * Clean up a prompt and process the next one in queue\n */\nfunction _isQueuedRequestCovered() {\n _isQueuedRequestCovered = _asyncToGenerator(function* (item) {\n const browserSessionData = yield getBrowserSessionData();\n if (!browserSessionData) return undefined;\n const currentIdentity = browserSessionData.identities.find(x => x.id === browserSessionData.selectedIdentityId);\n if (!currentIdentity) return undefined;\n // Parse host and method from the prompt URL query params.\n try {\n const url = new URL(item.url, 'http://ext');\n const host = url.searchParams.get('host');\n const method = url.searchParams.get('method');\n if (!host || !method) return undefined;\n return checkPermissions(browserSessionData, currentIdentity, host, method, {});\n } catch {\n return undefined;\n }\n });\n return _isQueuedRequestCovered.apply(this, arguments);\n}\nfunction cleanupPrompt(promptId, reason) {\n const promptData = openPrompts.get(promptId);\n if (promptData) {\n if (promptData.timeoutId) {\n clearTimeout(promptData.timeoutId);\n }\n if (reason !== 'response') {\n promptData.reject(new Error(`Permission prompt ${reason}`));\n }\n openPrompts.delete(promptId);\n }\n const queueIndex = permissionQueue.findIndex(item => item.id === promptId);\n if (queueIndex !== -1) {\n permissionQueue.splice(queueIndex, 1);\n }\n if (activePromptId === promptId) {\n activePromptId = null;\n }\n showNextPermissionPrompt();\n}\n/**\n * Queue a permission prompt request\n */\nfunction queuePermissionPrompt(urlWithoutId, width, height) {\n return new Promise((resolve, reject) => {\n if (permissionQueue.length >= MAX_PERMISSION_QUEUE_SIZE) {\n reject(new Error('Too many pending permission requests. Please try again later.'));\n return;\n }\n const id = crypto.randomUUID();\n const separator = urlWithoutId.includes('?') ? '&' : '?';\n const url = `${urlWithoutId}${separator}id=${id}`;\n openPrompts.set(id, {\n resolve,\n reject\n });\n permissionQueue.push({\n id,\n url,\n width,\n height,\n resolve,\n reject\n });\n debug(`Queued permission prompt ${id}. Queue size: ${permissionQueue.length}`);\n showNextPermissionPrompt();\n });\n}\n// Listen for window close events to clean up orphaned prompts and unlock popup\nbrowser.windows.onRemoved.addListener(windowId => {\n // Handle unlock popup closed without successful unlock\n if (unlockPopupWindowId === windowId) {\n debug('Unlock popup closed without successful unlock');\n unlockPopupOpen = false;\n unlockPopupWindowId = undefined;\n // Reject all pending requests — vault is still locked\n while (pendingRequests.length > 0) {\n const pending = pendingRequests.shift();\n pending.reject(new Error('Vault unlock cancelled'));\n }\n }\n for (const [promptId, promptData] of openPrompts.entries()) {\n if (promptData.windowId === windowId) {\n debug(`Prompt window ${windowId} closed without response`);\n cleanupPrompt(promptId, 'closed');\n break;\n }\n }\n});\n// ==========================================\n// Request Deduplication (P1)\n// ==========================================\nconst pendingRequestPromises = new Map();\n/**\n * Generate a hash key for request deduplication\n */\nfunction getRequestHash(host, method, params) {\n if (method === 'signEvent' && params?.kind !== undefined) {\n return `${host}:${method}:kind${params.kind}`;\n }\n // encrypt/decrypt permissions are blanket per host+method (no peerPubkey),\n // so dedup must match that granularity — one prompt covers all peers.\n return `${host}:${method}`;\n}\n/**\n * Queue a permission prompt with deduplication\n */\nfunction queuePermissionPromptDeduped(host, method, params, urlWithoutId, width, height) {\n const hash = getRequestHash(host, method, params);\n const existingPromise = pendingRequestPromises.get(hash);\n if (existingPromise) {\n debug(`Deduplicating request: ${hash}`);\n return existingPromise;\n }\n const promise = queuePermissionPrompt(urlWithoutId, width, height).finally(() => {\n pendingRequestPromises.delete(hash);\n });\n pendingRequestPromises.set(hash, promise);\n debug(`New permission request: ${hash}`);\n return promise;\n}\nbrowser.runtime.onMessage.addListener(/*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(function* (message, sender) {\n debug('Message received');\n // Handle unlock request from unlock popup\n if (message?.type === 'unlock-request') {\n const unlockReq = message;\n debug('Processing unlock request');\n const result = yield handleUnlockRequest(unlockReq.password);\n const response = {\n type: 'unlock-response',\n id: unlockReq.id,\n success: result.success,\n error: result.error\n };\n if (result.success) {\n unlockPopupOpen = false;\n unlockPopupWindowId = undefined;\n // Process pending requests asynchronously — don't block the response\n // to the unlock popup (Firefox may timeout the sendMessage otherwise).\n const queued = [...pendingRequests];\n pendingRequests.length = 0;\n if (queued.length > 0) {\n debug(`Scheduling ${queued.length} pending requests`);\n setTimeout(/*#__PURE__*/_asyncToGenerator(function* () {\n for (const pending of queued) {\n try {\n const pendingResult = yield processNip07Request(pending.request);\n pending.resolve(pendingResult);\n } catch (error) {\n pending.reject(error);\n }\n }\n }), 0);\n }\n }\n return response;\n }\n const request = message;\n debug(request);\n if (request?.id) {\n // Handle prompt response\n const promptResponse = request;\n const openPrompt = openPrompts.get(promptResponse.id);\n if (!openPrompt) {\n debug('Prompt response could not be matched (may have timed out)');\n return;\n }\n openPrompt.resolve(promptResponse.response);\n // If \"always\" (approve/reject/approve-all/reject-all), auto-resolve all\n // queued prompts for the same host:method so they never open a window.\n if (['approve', 'reject', 'approve-all', 'reject-all'].includes(promptResponse.response)) {\n const answeredItem = permissionQueue.find(item => item.id === promptResponse.id);\n if (answeredItem) {\n try {\n const answeredUrl = new URL(answeredItem.url, 'http://ext');\n const answeredHost = answeredUrl.searchParams.get('host');\n const answeredMethod = answeredUrl.searchParams.get('method');\n if (answeredHost && answeredMethod) {\n const autoResponse = ['approve', 'approve-all'].includes(promptResponse.response) ? 'approve-once' : 'reject-once';\n // Drain matching items from the queue (iterate in reverse to safely splice).\n for (let i = permissionQueue.length - 1; i >= 0; i--) {\n const item = permissionQueue[i];\n if (item.id === promptResponse.id) continue;\n try {\n const itemUrl = new URL(item.url, 'http://ext');\n if (itemUrl.searchParams.get('host') === answeredHost && itemUrl.searchParams.get('method') === answeredMethod) {\n const pd = openPrompts.get(item.id);\n if (pd) {\n if (pd.timeoutId) clearTimeout(pd.timeoutId);\n pd.resolve(autoResponse);\n openPrompts.delete(item.id);\n }\n permissionQueue.splice(i, 1);\n debug(`Auto-resolved queued prompt ${item.id} via ${promptResponse.response}`);\n }\n } catch {/* skip malformed */}\n }\n }\n } catch {/* skip malformed */}\n }\n }\n cleanupPrompt(promptResponse.id, 'response');\n return;\n }\n const browserSessionData = yield getBrowserSessionData();\n if (!browserSessionData) {\n // Vault is locked - open unlock popup and queue the request\n const req = request;\n debug('Vault locked, opening unlock popup');\n if (!unlockPopupOpen) {\n unlockPopupOpen = true;\n unlockPopupWindowId = yield openUnlockPopup(req.host);\n }\n // Queue this request to be processed after unlock\n return new Promise((resolve, reject) => {\n pendingRequests.push({\n request: req,\n resolve,\n reject\n });\n });\n }\n // Process the request (NIP-07 or WebLN)\n const req = request;\n if (isWeblnMethod(req.method)) {\n return processWeblnRequest(req);\n }\n const tabId = sender?.tab?.id;\n if (isMlsMethod(req.method) && tabId !== undefined) {\n mlsSetTab(tabId);\n }\n return processNip07Request(req, tabId);\n });\n return function (_x3, _x4) {\n return _ref2.apply(this, arguments);\n };\n}());\n/**\n * Process a NIP-07 request after vault is unlocked\n */\nfunction processNip07Request(_x5, _x6) {\n return _processNip07Request.apply(this, arguments);\n}\n/**\n * Process a WebLN request after vault is unlocked\n */\nfunction _processNip07Request() {\n _processNip07Request = _asyncToGenerator(function* (req, tabId) {\n const browserSessionData = yield getBrowserSessionData();\n if (!browserSessionData) {\n throw new Error('Smesh Signer vault not unlocked by the user.');\n }\n const currentIdentity = browserSessionData.identities.find(x => x.id === browserSessionData.selectedIdentityId);\n if (!currentIdentity) {\n throw new Error('No Nostr identity available at endpoint.');\n }\n // Check reckless mode first\n const recklessApprove = yield shouldRecklessModeApprove(req.host);\n debug(`recklessApprove result: ${recklessApprove}`);\n if (recklessApprove) {\n debug('Request auto-approved via reckless mode.');\n } else {\n // Normal permission flow\n const permissionState = checkPermissions(browserSessionData, currentIdentity, req.host, req.method, req.params);\n debug(`permissionState result: ${permissionState}`);\n if (permissionState === false) {\n throw new Error('Permission denied');\n }\n if (permissionState === undefined) {\n // Ask user for permission (queued + deduplicated)\n const width = 375;\n const height = 600;\n // MLS methods are a single permission group — prompt and store as 'mls.*'\n const isMls = req.method.startsWith('mls.');\n const promptMethod = isMls ? 'mls.*' : req.method;\n const base64Event = Buffer.from(JSON.stringify(req.params ?? {}, undefined, 2)).toString('base64');\n // Include queue info for user awareness\n const queueSize = permissionQueue.length;\n const promptUrl = `prompt.html?method=${promptMethod}&host=${req.host}&nick=${encodeURIComponent(currentIdentity.nick)}&event=${base64Event}&queue=${queueSize}`;\n const response = yield queuePermissionPromptDeduped(req.host, promptMethod, req.params, promptUrl, width, height);\n debug(response);\n // Handle permission storage based on response type\n if (response === 'approve' || response === 'reject') {\n const policy = response === 'approve' ? 'allow' : 'deny';\n yield storePermission(browserSessionData, currentIdentity, req.host, promptMethod, policy, req.params?.kind);\n yield backgroundLogPermissionStored(req.host, promptMethod, policy, req.params?.kind);\n } else if (response === 'approve-all') {\n yield storePermission(browserSessionData, currentIdentity, req.host, promptMethod, 'allow', undefined);\n yield backgroundLogPermissionStored(req.host, promptMethod, 'allow', undefined);\n debug(`Stored approve-all permission for ${promptMethod} from ${req.host}`);\n } else if (response === 'reject-all') {\n yield storePermission(browserSessionData, currentIdentity, req.host, promptMethod, 'deny', undefined);\n yield backgroundLogPermissionStored(req.host, promptMethod, 'deny', undefined);\n debug(`Stored reject-all permission for ${promptMethod} from ${req.host}`);\n }\n if (['reject', 'reject-once', 'reject-all'].includes(response)) {\n yield backgroundLogNip07Action(req.method, req.host, false, false, {\n kind: req.params?.kind,\n peerPubkey: req.params?.peerPubkey\n });\n throw new Error('Permission denied');\n }\n } else {\n debug('Request allowed (via saved permission).');\n }\n }\n const relays = {};\n let result;\n switch (req.method) {\n case 'getPublicKey':\n result = NostrHelper.pubkeyFromPrivkey(currentIdentity.privkey);\n yield backgroundLogNip07Action(req.method, req.host, true, recklessApprove);\n return result;\n case 'signEvent':\n result = signEvent(req.params, currentIdentity.privkey);\n yield backgroundLogNip07Action(req.method, req.host, true, recklessApprove, {\n kind: req.params?.kind\n });\n return result;\n case 'getRelays':\n browserSessionData.relays.forEach(x => {\n relays[x.url] = {\n read: x.read,\n write: x.write\n };\n });\n yield backgroundLogNip07Action(req.method, req.host, true, recklessApprove);\n return relays;\n case 'nip04.encrypt':\n result = yield nip04Encrypt(currentIdentity.privkey, req.params.peerPubkey, req.params.plaintext);\n yield backgroundLogNip07Action(req.method, req.host, true, recklessApprove, {\n peerPubkey: req.params.peerPubkey\n });\n return result;\n case 'nip44.encrypt':\n result = yield nip44Encrypt(currentIdentity.privkey, req.params.peerPubkey, req.params.plaintext);\n yield backgroundLogNip07Action(req.method, req.host, true, recklessApprove, {\n peerPubkey: req.params.peerPubkey\n });\n return result;\n case 'nip04.decrypt':\n result = yield nip04Decrypt(currentIdentity.privkey, req.params.peerPubkey, req.params.ciphertext);\n yield backgroundLogNip07Action(req.method, req.host, true, recklessApprove, {\n peerPubkey: req.params.peerPubkey\n });\n return result;\n case 'nip44.decrypt':\n result = yield nip44Decrypt(currentIdentity.privkey, req.params.peerPubkey, req.params.ciphertext);\n yield backgroundLogNip07Action(req.method, req.host, true, recklessApprove, {\n peerPubkey: req.params.peerPubkey\n });\n return result;\n // MLS operations — all crypto happens locally in the extension\n case 'mls.init':\n if (tabId === undefined) throw new Error('MLS requires tab context');\n result = yield mlsInit(currentIdentity.privkey, NostrHelper.pubkeyFromPrivkey(currentIdentity.privkey), req.params.relayURLs || [], tabId);\n return result;\n case 'mls.sendDM':\n return mlsSendDM(req.params.recipient, req.params.content);\n case 'mls.subscribe':\n return mlsSubscribe();\n case 'mls.publishKP':\n return mlsPublishKP();\n case 'mls.listGroups':\n return JSON.parse(yield mlsListGroups());\n case 'mls.deliverEvent':\n mlsDeliverEvent(req.params.subId, req.params.eventJSON);\n return 'ok';\n default:\n throw new Error(`Not supported request method '${req.method}'.`);\n }\n });\n return _processNip07Request.apply(this, arguments);\n}\nfunction processWeblnRequest(_x7) {\n return _processWeblnRequest.apply(this, arguments);\n}\nfunction _processWeblnRequest() {\n _processWeblnRequest = _asyncToGenerator(function* (req) {\n const browserSessionData = yield getBrowserSessionData();\n if (!browserSessionData) {\n throw new Error('Smesh Signer vault not unlocked by the user.');\n }\n const nwcConnections = browserSessionData.nwcConnections ?? [];\n const method = req.method;\n // webln.enable just checks if NWC is configured\n if (method === 'webln.enable') {\n if (nwcConnections.length === 0) {\n throw new Error('No wallet configured. Please add an NWC connection in Smesh Signer settings.');\n }\n debug('WebLN enabled');\n return {\n enabled: true\n }; // Return explicit value (undefined gets filtered by content script)\n }\n // All other methods require an NWC connection\n const defaultConnection = nwcConnections[0];\n if (!defaultConnection) {\n throw new Error('No wallet configured. Please add an NWC connection in Smesh Signer settings.');\n }\n // Check reckless mode (but still prompt for payments)\n const recklessApprove = yield shouldRecklessModeApprove(req.host);\n // Check WebLN permissions\n const permissionState = recklessApprove && method !== 'webln.sendPayment' && method !== 'webln.keysend' ? true : checkWeblnPermissions(browserSessionData, req.host, method);\n if (permissionState === false) {\n throw new Error('Permission denied');\n }\n if (permissionState === undefined) {\n // Ask user for permission (queued + deduplicated)\n const width = 375;\n const height = 600;\n // For sendPayment, include the invoice amount in the prompt data\n let promptParams = req.params ?? {};\n if (method === 'webln.sendPayment' && req.params?.paymentRequest) {\n const amountSats = parseInvoiceAmount(req.params.paymentRequest);\n promptParams = {\n ...promptParams,\n amountSats\n };\n }\n const base64Event = Buffer.from(JSON.stringify(promptParams, undefined, 2)).toString('base64');\n // Include queue info for user awareness\n const queueSize = permissionQueue.length;\n const promptUrl = `prompt.html?method=${method}&host=${req.host}&nick=WebLN&event=${base64Event}&queue=${queueSize}`;\n const response = yield queuePermissionPromptDeduped(req.host, method, req.params, promptUrl, width, height);\n debug(response);\n // Store permission for non-payment methods\n if ((response === 'approve' || response === 'reject') && method !== 'webln.sendPayment' && method !== 'webln.keysend') {\n const policy = response === 'approve' ? 'allow' : 'deny';\n yield storePermission(browserSessionData, null,\n // WebLN has no identity\n req.host, method, policy);\n yield backgroundLogPermissionStored(req.host, method, policy);\n } else if (response === 'approve-all' && method !== 'webln.sendPayment' && method !== 'webln.keysend') {\n // P2: Store permission for all uses of this WebLN method\n yield storePermission(browserSessionData, null, req.host, method, 'allow');\n yield backgroundLogPermissionStored(req.host, method, 'allow');\n debug(`Stored approve-all permission for ${method} from ${req.host}`);\n }\n if (['reject', 'reject-once', 'reject-all'].includes(response)) {\n throw new Error('Permission denied');\n }\n }\n // Execute the WebLN method\n let result;\n const client = yield getNwcClient(defaultConnection);\n switch (method) {\n case 'webln.getInfo':\n {\n const info = yield client.getInfo();\n result = {\n node: {\n alias: info.alias,\n pubkey: info.pubkey,\n color: info.color\n }\n };\n debug('webln.getInfo result:');\n debug(result);\n return result;\n }\n case 'webln.sendPayment':\n {\n const invoice = req.params.paymentRequest;\n const payResult = yield client.payInvoice({\n invoice\n });\n result = {\n preimage: payResult.preimage\n };\n debug('webln.sendPayment result:');\n debug(result);\n return result;\n }\n case 'webln.makeInvoice':\n {\n // Convert sats to millisats (NWC uses millisats)\n const amountSats = typeof req.params.amount === 'string' ? parseInt(req.params.amount, 10) : req.params.amount ?? req.params.defaultAmount ?? 0;\n const amountMsat = amountSats * 1000;\n const invoiceResult = yield client.makeInvoice({\n amount: amountMsat,\n description: req.params.defaultMemo\n });\n result = {\n paymentRequest: invoiceResult.invoice\n };\n debug('webln.makeInvoice result:');\n debug(result);\n return result;\n }\n case 'webln.keysend':\n throw new Error('keysend is not yet supported');\n default:\n throw new Error(`Not supported WebLN method '${method}'.`);\n }\n });\n return _processWeblnRequest.apply(this, arguments);\n}","map":null,"metadata":{},"sourceType":"module","externalDependencies":[]}