Skip to content

Commit

Permalink
LN Address support (#507)
Browse files Browse the repository at this point in the history
* LN Address support

* Bug fixes and code refactoring

* Removes declared and non used functions
  • Loading branch information
grunch authored Apr 22, 2024
1 parent 24588e4 commit b94e87c
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 34 deletions.
11 changes: 6 additions & 5 deletions bot/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,13 @@ const addInvoice = async (ctx, bot, order) => {
logger.error(
`lightning address ${buyer.lightning_address} not available`
);
messages.unavailableLightningAddress(
ctx,
bot,
buyer,
buyer.lightning_address
await bot.telegram.sendMessage(
buyer.tg_id,
ctx.i18n.t('unavailable_lightning_address', {
la: buyer.lightning_address,
})
);

ctx.scene.enter('ADD_INVOICE_WIZARD_SCENE_ID', {
order,
seller,
Expand Down
12 changes: 0 additions & 12 deletions bot/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -710,17 +710,6 @@ const invalidLightningAddress = async (ctx: MainContext) => {
}
};

const unavailableLightningAddress = async (ctx: MainContext, bot: Telegraf<MainContext>, user: UserDocument, la: string) => {
try {
await bot.telegram.sendMessage(
user.tg_id,
ctx.i18n.t('unavailable_lightning_address', { la })
);
} catch (error) {
logger.error(error);
}
};

const helpMessage = async (ctx: MainContext) => {
try {
await ctx.reply(ctx.i18n.t('help'), { parse_mode: 'Markdown' });
Expand Down Expand Up @@ -1650,7 +1639,6 @@ module.exports = {
checkOrderMessage,
mustBeValidCurrency,
mustBeANumberOrRange,
unavailableLightningAddress,
invalidLightningAddress,
helpMessage,
disclaimerMessage,
Expand Down
38 changes: 29 additions & 9 deletions bot/scenes.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
const { Scenes } = require('telegraf');
const { isValidInvoice } = require('./validations');
const { parsePaymentRequest } = require('invoices');
const { isValidInvoice, validateLightningAddress } = require('./validations');
const { Order, PendingPayment } = require('../models');
const { waitPayment, addInvoice, showHoldInvoice } = require('./commands');
const { getCurrency, getUserI18nContext } = require('../util');
const messages = require('./messages');
const { isPendingPayment } = require('../ln');
const { logger } = require('../logger');
const { resolvLightningAddress } = require('../lnurl/lnurl-pay');

const addInvoiceWizard = new Scenes.WizardScene(
'ADD_INVOICE_WIZARD_SCENE_ID',
Expand Down Expand Up @@ -34,7 +36,6 @@ const addInvoiceWizard = new Scenes.WizardScene(
if (ctx.message.document)
return await ctx.reply(ctx.i18n.t('must_enter_text'));

const lnInvoice = ctx.message.text.trim();
let { bot, buyer, seller, order } = ctx.wizard.state;
// We get an updated order from the DB
order = await Order.findOne({ _id: order._id });
Expand All @@ -43,9 +44,19 @@ const addInvoiceWizard = new Scenes.WizardScene(
return ctx.scene.leave();
}

const res = await isValidInvoice(ctx, lnInvoice);
if (!res.success) {
return;
let lnInvoice = ctx.message.text.trim();
const isValidLN = await validateLightningAddress(lnInvoice);
let res = {};
if (isValidLN) {
const laRes = await resolvLightningAddress(
lnInvoice,
order.amount * 1000
);
lnInvoice = laRes.pr;
res.invoice = parsePaymentRequest({ request: lnInvoice });
} else {
res = await isValidInvoice(ctx, lnInvoice);
if (!res.success) return;
}

if (order.status === 'EXPIRED') {
Expand Down Expand Up @@ -90,7 +101,6 @@ const addInvoicePHIWizard = new Scenes.WizardScene(
if (ctx.message.document)
return await ctx.reply(ctx.i18n.t('must_enter_text'));

const lnInvoice = ctx.message.text.trim();
let { buyer, order } = ctx.wizard.state;
// We get an updated order from the DB
order = await Order.findOne({ _id: order._id });
Expand All @@ -99,9 +109,19 @@ const addInvoicePHIWizard = new Scenes.WizardScene(
return ctx.scene.leave();
}

const res = await isValidInvoice(ctx, lnInvoice);
if (!res.success) {
return;
let lnInvoice = ctx.message.text.trim();
const isValidLN = await validateLightningAddress(lnInvoice);
let res = {};
if (isValidLN) {
const laRes = await resolvLightningAddress(
lnInvoice,
order.amount * 1000
);
lnInvoice = laRes.pr;
res.invoice = parsePaymentRequest({ request: lnInvoice });
} else {
res = await isValidInvoice(ctx, lnInvoice);
if (!res.success) return;
}

if (!!res.invoice.tokens && res.invoice.tokens !== order.amount)
Expand Down
3 changes: 0 additions & 3 deletions bot/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ const {
addInvoice,
cancelShowHoldInvoice,
showHoldInvoice,
waitPayment,
addInvoicePHI,
cancelOrder,
fiatSent,
Expand All @@ -45,15 +44,13 @@ const {
settleHoldInvoice,
cancelHoldInvoice,
payToBuyer,
isPendingPayment,
subscribeInvoice,
getInvoice,
} = require('../ln');
const {
validateUser,
validateParams,
validateObjectId,
validateInvoice,
validateLightningAddress,
} = require('./validations');
const messages = require('./messages');
Expand Down
5 changes: 2 additions & 3 deletions bot/validations.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,9 @@ const validateBuyOrder = async ctx => {
};
const validateLightningAddress = async lightningAddress => {
const pattern = /^[\w-.]+@(?:[\w-]+(?<!-)\.)+(?:[A-Za-z]{2,63})$/;
const lnExists = await existLightningAddress(lightningAddress);

return (
pattern.test(lightningAddress) && existLightningAddress(lightningAddress)
);
return pattern.test(lightningAddress) && lnExists;
};

const validateInvoice = async (ctx, lnInvoice) => {
Expand Down
4 changes: 2 additions & 2 deletions lnurl/lnurl-pay.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ const existLightningAddress = async address => {
const lnAddressQuery = `https://${domain}/.well-known/lnurlp/${user}`;

try {
const lnAddressRes = (await axios.get(lnAddressQuery)).data;
if (lnAddressRes.tag !== 'payRequest') {
const lnAddressRes = await axios.get(lnAddressQuery, { timeout: 3000 });
if (lnAddressRes.data.tag !== 'payRequest') {
logger.info('Invalid response from LNURL');
return false;
}
Expand Down

0 comments on commit b94e87c

Please sign in to comment.