Compare commits

..

1 commit

Author SHA1 Message Date
Patrick Mulligan
4fea2aa1b1 feat(extensions): add NIP-05 identity extension
Some checks are pending
Docker Compose Actions Workflow / test (push) Waiting to run
Implements Nostr NIP-05 for human-readable identity verification:
- Username claiming and management (username@domain)
- /.well-known/nostr.json endpoint per spec
- Optional relay hints in JSON response
- Admin controls for identity management

RPC methods:
- nip05.claim - Claim a username
- nip05.release - Release your username
- nip05.updateRelays - Update relay hints
- nip05.getMyIdentity - Get your identity
- nip05.lookup - Look up by username
- nip05.lookupByPubkey - Look up by pubkey
- nip05.listIdentities - List all (admin)
- nip05.deactivate/reactivate - Admin controls

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 14:28:20 -05:00
3 changed files with 1 additions and 118 deletions

View file

@ -8,8 +8,7 @@ import {
PaymentReceivedData,
NostrEvent,
UnsignedNostrEvent,
RpcMethodHandler,
LnurlPayInfo
RpcMethodHandler
} from './types.js'
/**
@ -45,15 +44,6 @@ export interface MainHandlerInterface {
paymentHash: string
feeSats: number
}>
/**
* Get LNURL-pay info for a user by their Nostr pubkey
* This enables Lightning Address (LUD-16) and zap (NIP-57) support
*/
getLnurlPayInfoByPubkey(pubkeyHex: string, options?: {
metadata?: string
description?: string
}): Promise<LnurlPayInfo>
}
// Nostr operations
@ -187,17 +177,6 @@ export class ExtensionContextImpl implements ExtensionContext {
return this.mainHandler.sendNostrEvent(event)
}
/**
* Get LNURL-pay info for a user by pubkey
* Enables Lightning Address and zap support
*/
async getLnurlPayInfo(pubkeyHex: string, options?: {
metadata?: string
description?: string
}): Promise<LnurlPayInfo> {
return this.mainHandler.paymentManager.getLnurlPayInfoByPubkey(pubkeyHex, options)
}
/**
* Subscribe to payment received callbacks
*/

View file

@ -94,13 +94,6 @@ export default class Nip05Extension implements Extension {
method: 'GET',
path: '/api/v1/nip05/nostr.json',
handler: this.handleNostrJson.bind(this)
},
// Lightning Address endpoint (LUD-16)
// Makes NIP-05 usernames work as Lightning Addresses for zaps
{
method: 'GET',
path: '/.well-known/lnurlp/:username',
handler: this.handleLnurlPay.bind(this)
}
]
}
@ -227,72 +220,6 @@ export default class Nip05Extension implements Extension {
}
}
}
/**
* Handle /.well-known/lnurlp/:username request (Lightning Address / LUD-16)
*
* This enables NIP-05 usernames to work as Lightning Addresses for receiving
* payments and zaps. When someone sends to alice@domain.com:
* 1. Wallet resolves /.well-known/lnurlp/alice
* 2. We look up alice -> pubkey in our NIP-05 database
* 3. We return LNURL-pay info from Lightning.Pub for that user
*/
private async handleLnurlPay(req: HttpRequest): Promise<HttpResponse> {
try {
const { username } = req.params
const appId = req.headers['x-application-id'] || 'default'
if (!username) {
return {
status: 400,
body: { status: 'ERROR', reason: 'Username required' },
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
}
}
// Look up the username in our NIP-05 database
const lookup = await this.manager.lookupUsername(appId, username)
if (!lookup.found || !lookup.identity) {
return {
status: 404,
body: { status: 'ERROR', reason: 'User not found' },
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
}
}
// Get LNURL-pay info from Lightning.Pub for this user's pubkey
const lnurlPayInfo = await this.ctx.getLnurlPayInfo(lookup.identity.pubkey_hex, {
description: `Pay to ${username}`
})
return {
status: 200,
body: lnurlPayInfo,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Cache-Control': 'max-age=60' // Cache for 1 minute
}
}
} catch (error) {
this.ctx.log('error', `Error handling lnurlp: ${error}`)
return {
status: 500,
body: { status: 'ERROR', reason: 'Internal server error' },
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
}
}
}
}
// Export types for external use

View file

@ -77,20 +77,6 @@ export interface PaymentReceivedData {
metadata?: Record<string, any>
}
/**
* LNURL-pay info response (LUD-06/LUD-16)
* Used for Lightning Address and zap support
*/
export interface LnurlPayInfo {
tag: 'payRequest'
callback: string // URL to call with amount
minSendable: number // Minimum msats
maxSendable: number // Maximum msats
metadata: string // JSON-encoded metadata array
allowsNostr?: boolean // Whether zaps are supported
nostrPubkey?: string // Pubkey for zap receipts (hex)
}
/**
* Nostr event structure (minimal)
*/
@ -156,15 +142,6 @@ export interface ExtensionContext {
*/
publishNostrEvent(event: UnsignedNostrEvent): Promise<string | null>
/**
* Get LNURL-pay info for a user (by pubkey)
* Used to enable Lightning Address support (LUD-16) and zaps (NIP-57)
*/
getLnurlPayInfo(pubkeyHex: string, options?: {
metadata?: string // Custom metadata JSON
description?: string // Human-readable description
}): Promise<LnurlPayInfo>
/**
* Subscribe to payment received callbacks
*/