mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 03:19:46 +00:00
71 lines
1.9 KiB
TypeScript
71 lines
1.9 KiB
TypeScript
import { LNURL, LNURLDetails } from '@nostrify/nostrify/ln';
|
|
import { Stickynotes } from '@soapbox/stickynotes';
|
|
|
|
import { cachedLnurlsSizeGauge } from '@/metrics.ts';
|
|
import { SimpleLRU } from '@/utils/SimpleLRU.ts';
|
|
import { Time } from '@/utils/time.ts';
|
|
import { fetchWorker } from '@/workers/fetch.ts';
|
|
import { NostrEvent } from '@nostrify/nostrify';
|
|
|
|
const console = new Stickynotes('ditto:lnurl');
|
|
|
|
const lnurlCache = new SimpleLRU<string, LNURLDetails>(
|
|
async (lnurl, { signal }) => {
|
|
console.debug(`Lookup ${lnurl}`);
|
|
try {
|
|
const result = await LNURL.lookup(lnurl, { fetch: fetchWorker, signal });
|
|
console.debug(`Found: ${lnurl}`);
|
|
return result;
|
|
} catch (e) {
|
|
console.debug(`Not found: ${lnurl}`);
|
|
throw e;
|
|
}
|
|
},
|
|
{ max: 1000, ttl: Time.minutes(30), gauge: cachedLnurlsSizeGauge },
|
|
);
|
|
|
|
/** Get an LNURL from a lud06 or lud16. */
|
|
function getLnurl({ lud06, lud16 }: { lud06?: string; lud16?: string }, limit?: number): string | undefined {
|
|
if (lud06) return lud06;
|
|
if (lud16) {
|
|
const [name, host] = lud16.split('@');
|
|
if (name && host) {
|
|
try {
|
|
const url = new URL(`/.well-known/lnurlp/${name}`, `https://${host}`);
|
|
return LNURL.encode(url, limit);
|
|
} catch {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
interface CallbackParams {
|
|
amount: number;
|
|
nostr: NostrEvent;
|
|
lnurl: string;
|
|
}
|
|
|
|
async function getInvoice(params: CallbackParams, signal?: AbortSignal): Promise<string> {
|
|
const { amount, lnurl } = params;
|
|
|
|
const details = await lnurlCache.fetch(lnurl, { signal });
|
|
|
|
if (details.tag !== 'payRequest' || !details.allowsNostr || !details.nostrPubkey) {
|
|
throw new Error('invalid lnurl');
|
|
}
|
|
|
|
if (amount > details.maxSendable || amount < details.minSendable) {
|
|
throw new Error('amount out of range');
|
|
}
|
|
|
|
const { pr } = await LNURL.callback(
|
|
details.callback,
|
|
params,
|
|
{ fetch: fetchWorker, signal },
|
|
);
|
|
|
|
return pr;
|
|
}
|
|
|
|
export { getInvoice, getLnurl, lnurlCache };
|