mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-06-06 18:31:00 +00:00
Add nip05 and lnaddress endpoints
This commit is contained in:
parent
365b54c498
commit
ff3e907677
@ -14,6 +14,10 @@ module.exports = removeImports({
|
|||||||
source: '/api/cron',
|
source: '/api/cron',
|
||||||
destination: '/api/cron',
|
destination: '/api/cron',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
source: "/.well-known/nostr.json",
|
||||||
|
destination: "/api/nip05",
|
||||||
|
}
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
});
|
});
|
65
src/pages/api/lightning-address/callback/[slug].js
Normal file
65
src/pages/api/lightning-address/callback/[slug].js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import crypto from "crypto";
|
||||||
|
import { runMiddleware, corsMiddleware } from "../../../utils/middleware";
|
||||||
|
import { verifyEvent } from 'nostr-tools/pure';
|
||||||
|
|
||||||
|
const BACKEND_URL = process.env.BACKEND_URL;
|
||||||
|
const RELAY_PUBKEY = process.env.RELAY_PUBKEY;
|
||||||
|
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
await runMiddleware(req, res, corsMiddleware);
|
||||||
|
const { slug, ...queryParams } = req.query;
|
||||||
|
|
||||||
|
if (slug === 'austin') {
|
||||||
|
if (queryParams.amount) {
|
||||||
|
const amount = parseInt(queryParams.amount);
|
||||||
|
let metadata, metadataString, hash, descriptionHash;
|
||||||
|
|
||||||
|
if (queryParams.nostr) {
|
||||||
|
// This is a zap request
|
||||||
|
const zapRequest = JSON.parse(decodeURIComponent(queryParams.nostr));
|
||||||
|
|
||||||
|
// Verify the zap request
|
||||||
|
if (!verifyEvent(zapRequest)) {
|
||||||
|
res.status(400).json({ error: 'Invalid zap request' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate zap request
|
||||||
|
if (zapRequest.kind !== 9734) {
|
||||||
|
res.status(400).json({ error: 'Invalid zap request' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
metadataString = JSON.stringify(zapRequest);
|
||||||
|
hash = crypto.createHash('sha256').update(metadataString).digest('hex');
|
||||||
|
descriptionHash = Buffer.from(hash, 'hex').toString('base64');
|
||||||
|
} else {
|
||||||
|
// This is a regular lnurl-pay request
|
||||||
|
metadata = [
|
||||||
|
["text/plain", "PlebDevs LNURL endpoint, CHEERS!"]
|
||||||
|
];
|
||||||
|
metadataString = JSON.stringify(metadata);
|
||||||
|
hash = crypto.createHash('sha256').update(metadataString).digest('hex');
|
||||||
|
descriptionHash = Buffer.from(hash, 'hex').toString('base64');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert amount from millisatoshis to satoshis
|
||||||
|
const value = amount / 1000;
|
||||||
|
if (value < 1) {
|
||||||
|
res.status(400).json({ error: 'Amount too low' });
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`${BACKEND_URL}/api/lnd`, { amount: value, description_hash: descriptionHash });
|
||||||
|
res.status(200).json({ pr: response.data });
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
res.status(500).json({ error: 'Failed to generate invoice' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.status(400).json({ error: 'Amount not specified' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
src/pages/api/lightning-address/lnd.js
Normal file
50
src/pages/api/lightning-address/lnd.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import { finalizeEvent } from 'nostr-tools/pure';
|
||||||
|
import { SimplePool } from 'nostr-tools/pool';
|
||||||
|
|
||||||
|
const LND_HOST = process.env.LND_HOST;
|
||||||
|
const LND_MACAROON = process.env.LND_MACAROON;
|
||||||
|
const RELAY_PRIVKEY = process.env.RELAY_PRIVKEY;
|
||||||
|
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`https://${LND_HOST}/v1/invoices`, {
|
||||||
|
value: req.body.amount,
|
||||||
|
description_hash: req.body.description_hash
|
||||||
|
}, {
|
||||||
|
headers: {
|
||||||
|
'Grpc-Metadata-macaroon': LND_MACAROON,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const invoice = response.data.payment_request;
|
||||||
|
|
||||||
|
// If this is a zap, publish a zap receipt
|
||||||
|
if (req.body.zap_request) {
|
||||||
|
const zapRequest = JSON.parse(req.body.zap_request);
|
||||||
|
const zapReceipt = {
|
||||||
|
kind: 9735,
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
content: '',
|
||||||
|
tags: [
|
||||||
|
['p', zapRequest.pubkey],
|
||||||
|
['e', zapRequest.id],
|
||||||
|
['bolt11', invoice],
|
||||||
|
['description', JSON.stringify(zapRequest)]
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const signedZapReceipt = finalizeEvent(zapReceipt, RELAY_PRIVKEY);
|
||||||
|
|
||||||
|
// Publish zap receipt to relays
|
||||||
|
const pool = new SimplePool();
|
||||||
|
const relays = zapRequest.tags.find(tag => tag[0] === 'relays')?.[1] || [];
|
||||||
|
await pool.publish(relays, signedZapReceipt);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json(invoice);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error (server) fetching data from LND:', error.message);
|
||||||
|
res.status(500).json({ message: 'Error fetching data' });
|
||||||
|
}
|
||||||
|
}
|
32
src/pages/api/lightning-address/lnurlp/[slug].js
Normal file
32
src/pages/api/lightning-address/lnurlp/[slug].js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { runMiddleware, corsMiddleware } from "../../../utils/middleware"
|
||||||
|
|
||||||
|
const BACKEND_URL = process.env.BACKEND_URL
|
||||||
|
const RELAY_PUBKEY = process.env.RELAY_PUBKEY
|
||||||
|
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
await runMiddleware(req, res, corsMiddleware);
|
||||||
|
|
||||||
|
const { slug } = req.query
|
||||||
|
|
||||||
|
if (!slug || slug === 'undefined') {
|
||||||
|
res.status(404).json({ error: 'Not found' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slug === 'austin') {
|
||||||
|
const metadata = [
|
||||||
|
["text/plain", "PlebDevs LNURL endpoint, CHEERS!"]
|
||||||
|
];
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
callback: `${BACKEND_URL}/api/callback/austin`,
|
||||||
|
maxSendable: 10000000000,
|
||||||
|
minSendable: 1000,
|
||||||
|
metadata: JSON.stringify(metadata),
|
||||||
|
tag: 'payRequest',
|
||||||
|
allowsNostr: true,
|
||||||
|
nostrPubkey: RELAY_PUBKEY
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
10
src/pages/api/nip05.js
Normal file
10
src/pages/api/nip05.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
const nostrData = {
|
||||||
|
names: {
|
||||||
|
plebdevs:
|
||||||
|
"f33c8a9617cb15f705fc70cd461cfd6eaf22f9e24c33eabad981648e5ec6f741",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default async function Nip05(req, res) {
|
||||||
|
return res.status(200).json(nostrData);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user