diff --git a/bot/commands.ts b/bot/commands.ts index 6d6f95bc..9f69bb2f 100644 --- a/bot/commands.ts +++ b/bot/commands.ts @@ -54,10 +54,14 @@ const waitPayment = async (ctx: MainContext, bot: HasTelegram, buyer: UserDocume fiatAmount: order.fiat_amount, }); const amount = Math.floor(order.amount + order.fee); - const { hash, secret } = await createHoldInvoice({ + const createHoldInvoiceResult = await createHoldInvoice({ amount, description, }); + if (createHoldInvoiceResult === undefined) { + throw new Error("createHoldInvoice() returned undefined"); + } + const { hash, secret } = createHoldInvoiceResult; order.hash = hash; order.secret = secret; order.taken_at = new Date(); @@ -245,6 +249,8 @@ const cancelAddInvoice = async (ctx: CommunityContext, order: IOrder | null = nu ctx.deleteMessage(); ctx.scene.leave(); userAction = true; + if (ctx.from === undefined) + throw new Error("ctx.from is undefined"); userTgId = String(ctx.from.id); if (order === null) { const orderId = !!ctx && (ctx.update as any).callback_query.message.text; @@ -255,6 +261,9 @@ const cancelAddInvoice = async (ctx: CommunityContext, order: IOrder | null = nu if (order === null) return; // We make sure the seller can't send us sats now + if (order.hash === null){ + throw new Error("order.hash is null"); + } await cancelHoldInvoice({ hash: order.hash }); const user = await User.findOne({ _id: order.buyer_id }); @@ -270,6 +279,8 @@ const cancelAddInvoice = async (ctx: CommunityContext, order: IOrder | null = nu if(sellerUser === null) throw new Error("sellerUser was not found"); const buyerUser = await User.findOne({ _id: order.buyer_id }); + if(buyerUser === null) + throw new Error("buyerUser was not found"); const sellerTgId = sellerUser.tg_id; // If order creator cancels it, it will not be republished if (order.creator_id === order.buyer_id) { @@ -362,7 +373,7 @@ const showHoldInvoice = async (ctx: CommunityContext, bot: HasTelegram, order?: const orderId = (ctx.update as any).callback_query?.message?.text; if (!orderId) return; order = await Order.findOne({ _id: orderId }); - if (order === null) return; + if (order === null || order === undefined) return; } const user = await User.findOne({ _id: order.seller_id }); @@ -408,10 +419,14 @@ const showHoldInvoice = async (ctx: CommunityContext, bot: HasTelegram, order?: Math.floor(order.amount) : Math.floor(order.amount + order.fee); - const { request, hash, secret } = await createHoldInvoice({ + const holdInvoice = await createHoldInvoice({ description, amount, }); + if (holdInvoice === undefined) { + throw new Error("createHoldInvoice returned undefined"); + } + const { request, hash, secret } = holdInvoice; order.hash = hash; order.secret = secret; await order.save(); @@ -441,6 +456,8 @@ const cancelShowHoldInvoice = async (ctx: CommunityContext, order: IOrder | null ctx.deleteMessage(); ctx.scene.leave(); userAction = true; + if (ctx.from === undefined) + throw new Error("ctx.from is undefined"); userTgId = String(ctx.from.id); if (order === null) { const orderId = !!ctx && (ctx.update as any).callback_query.message.text; @@ -450,6 +467,9 @@ const cancelShowHoldInvoice = async (ctx: CommunityContext, order: IOrder | null } if (order === null) return; + if (order.hash === null) { + throw new Error("order.hash is null"); + } // We make sure the seller can't send us sats now await cancelHoldInvoice({ hash: order.hash }); @@ -464,6 +484,8 @@ const cancelShowHoldInvoice = async (ctx: CommunityContext, order: IOrder | null if(buyerUser === null) throw new Error("buyerUser was not found"); const sellerUser = await User.findOne({ _id: order.seller_id }); + if(sellerUser === null) + throw new Error("sellerUser was not found"); const buyerTgId = buyerUser.tg_id; // If order creator cancels it, it will not be republished if (order.creator_id === order.seller_id) { @@ -624,7 +646,7 @@ const cancelOrder = async (ctx: CommunityContext, orderId: string, user: UserDoc if (order.type === 'sell') { const seller = await User.findById(order.seller_id); if (!seller) throw new Error('sellerUser was not found'); - if (String(ctx.from.id) === seller.tg_id) { + if (String(ctx.from?.id) === seller.tg_id) { return cancelShowHoldInvoice(ctx, order); } } @@ -773,6 +795,9 @@ const release = async (ctx: MainContext, orderId: string, user: UserDocument | n await dispute.save(); } + if (order.secret === null) { + throw new Error("order.secret is null"); + } await settleHoldInvoice({ secret: order.secret }); } catch (error) { logger.error(error); diff --git a/bot/messages.ts b/bot/messages.ts index ebadd2e9..cd3c115d 100644 --- a/bot/messages.ts +++ b/bot/messages.ts @@ -412,7 +412,7 @@ const showHoldInvoiceMessage = async ( await ctx.reply( ctx.i18n.t('pay_invoice', { amount: numberFormat(fiatCode, amount), - fiatAmount: numberFormat(fiatCode, fiatAmount), + fiatAmount: numberFormat(fiatCode, fiatAmount!), currency: currencySymbol, }) ); diff --git a/bot/modules/block/commands.ts b/bot/modules/block/commands.ts index 5bfa6946..bcde8f09 100644 --- a/bot/modules/block/commands.ts +++ b/bot/modules/block/commands.ts @@ -1,10 +1,9 @@ -import { CustomContext } from './customContext'; +import { User, Block, Order } from '../../../models'; +import * as messages from './messages'; +import * as globalMessages from '../../messages'; +import { MainContext } from '../../start'; -const { User, Block, Order } = require('../../../models'); -const messages = require('./messages'); -const globalMessages = require('../../messages'); - -const block = async (ctx: CustomContext, username: string): Promise => { +const block = async (ctx: MainContext, username: string): Promise => { const userToBlock = await User.findOne({ username: username.substring(1) }); const user = ctx.user; @@ -54,7 +53,7 @@ const block = async (ctx: CustomContext, username: string): Promise => { await messages.userBlocked(ctx); }; -const unblock = async (ctx: CustomContext, username: string): Promise => { +const unblock = async (ctx: MainContext, username: string): Promise => { const userToUnblock = await User.findOne({ username: username.substring(1) }); if (!userToUnblock) { await globalMessages.notFoundUserMessage(ctx); @@ -74,9 +73,9 @@ const unblock = async (ctx: CustomContext, username: string): Promise => { } }; -const blocklist = async (ctx: CustomContext): Promise => { +const blocklist = async (ctx: MainContext): Promise => { const blocks = await Block.find({ blocker_tg_id: ctx.user.tg_id }); - const tgIdBlocks = blocks.map(blocked => blocked.blocked_tg_id); + const tgIdBlocks = blocks.map((blocked: { blocked_tg_id: any; }) => blocked.blocked_tg_id); if (!tgIdBlocks.length) { await messages.blocklistEmptyMessage(ctx); diff --git a/bot/modules/block/customContext.ts b/bot/modules/block/customContext.ts deleted file mode 100644 index 79d641ba..00000000 --- a/bot/modules/block/customContext.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Context } from 'telegraf'; - -export interface CustomContext extends Context { - user?: { - id: string; - tg_id: string; - }, - i18n?: { - t: (key: string, params?: Record) => string; - }; -} diff --git a/bot/modules/block/messages.ts b/bot/modules/block/messages.ts index bc3475aa..0b624bd8 100644 --- a/bot/modules/block/messages.ts +++ b/bot/modules/block/messages.ts @@ -1,8 +1,9 @@ -import { CustomContext } from './customContext'; +import { UserDocument } from '../../../models/user'; +import { MainContext } from '../../start'; const { logger } = require('../../../logger'); -const ordersInProcess = async (ctx: CustomContext) => { +const ordersInProcess = async (ctx: MainContext) => { try { ctx.reply(ctx.i18n.t('orders_in_process')); } catch (error) { @@ -10,7 +11,7 @@ const ordersInProcess = async (ctx: CustomContext) => { } }; -const userAlreadyBlocked = async (ctx: CustomContext) => { +const userAlreadyBlocked = async (ctx: MainContext) => { try { ctx.reply(ctx.i18n.t('user_already_blocked')); } catch (error) { @@ -18,7 +19,7 @@ const userAlreadyBlocked = async (ctx: CustomContext) => { } }; -const userBlocked = async (ctx: CustomContext) => { +const userBlocked = async (ctx: MainContext) => { try { ctx.reply(ctx.i18n.t('user_blocked')); } catch (error) { @@ -26,7 +27,7 @@ const userBlocked = async (ctx: CustomContext) => { } }; -const userUnblocked = async (ctx: CustomContext) => { +const userUnblocked = async (ctx: MainContext) => { try { ctx.reply(ctx.i18n.t('user_unblocked')); } catch (error) { @@ -34,7 +35,7 @@ const userUnblocked = async (ctx: CustomContext) => { } }; -const blocklistMessage = async (ctx: CustomContext, usersBlocked) => { +const blocklistMessage = async (ctx: MainContext, usersBlocked: UserDocument[]) => { try { if (!usersBlocked?.length) { return await blocklistEmptyMessage(ctx); @@ -46,7 +47,7 @@ const blocklistMessage = async (ctx: CustomContext, usersBlocked) => { } }; -const blocklistEmptyMessage = async (ctx: CustomContext) => { +const blocklistEmptyMessage = async (ctx: MainContext) => { try { ctx.reply(ctx.i18n.t('blocklist_empty')); } catch (error) { diff --git a/bot/modules/nostr/events.ts b/bot/modules/nostr/events.ts index d591c998..0cdf8a6a 100644 --- a/bot/modules/nostr/events.ts +++ b/bot/modules/nostr/events.ts @@ -40,7 +40,7 @@ const orderToTags = async (order: IOrder) => { const community = await Community.findById(order.community_id); if(community === null) throw new Error("community was not found"); - let order_channel: string; + let order_channel: string = ""; if (community.order_channels.length === 1) order_channel = removeAtSymbol(community.order_channels[0].name); else if (community.order_channels.length === 2){ diff --git a/bot/modules/orders/takeOrder.ts b/bot/modules/orders/takeOrder.ts index e0bbad43..5eca5010 100644 --- a/bot/modules/orders/takeOrder.ts +++ b/bot/modules/orders/takeOrder.ts @@ -1,5 +1,6 @@ import { logger } from '../../../logger'; import { Block, Order, User } from '../../../models'; +import { UserDocument } from '../../../models/user'; import { deleteOrderFromChannel, generateRandomImage } from '../../../util'; import * as messages from '../../messages'; import { HasTelegram, MainContext } from '../../start'; @@ -105,6 +106,9 @@ export const takesell = async ( const order = await Order.findOne({ _id: orderId }); if (!order) return; const seller = await User.findOne({ _id: order.seller_id }); + if(seller === null) { + throw new Error("seller is null"); + } const sellerIsBlocked = await Block.exists({ blocker_tg_id: user.tg_id, @@ -140,7 +144,7 @@ export const takesell = async ( } }; -const checkBlockingStatus = async (ctx, user, otherUser) => { +const checkBlockingStatus = async (ctx: MainContext, user: UserDocument, otherUser: UserDocument) => { const userIsBlocked = await Block.exists({ blocker_tg_id: user.tg_id, blocked_tg_id: otherUser.tg_id, diff --git a/bot/scenes.ts b/bot/scenes.ts index 9fff239e..d1fa44b4 100644 --- a/bot/scenes.ts +++ b/bot/scenes.ts @@ -1,4 +1,5 @@ import { Scenes } from 'telegraf'; +// @ts-ignore import { parsePaymentRequest } from 'invoices'; import { isValidInvoice, validateLightningAddress } from './validations'; import { Order, PendingPayment } from '../models'; diff --git a/bot/start.ts b/bot/start.ts index 75e6bcdc..ff0647d4 100644 --- a/bot/start.ts +++ b/bot/start.ts @@ -161,7 +161,7 @@ export const ctxUpdateAssertMsg = "ctx.update.message.text is not available."; const COMMIT_HASH = (() => { try { return execSync('git rev-parse HEAD', { encoding: 'utf8' }).trim(); - } catch (e) { + } catch (e: any) { logger.warning(`Could not retrieve Git commit hash: ${e.message}`); return 'unknown'; } @@ -218,7 +218,7 @@ const initialize = (botToken: string, options: Partial { - await checkSolvers(bot); + await checkSolvers(bot as any as Telegraf); }); bot.start(async (ctx: MainContext) => { @@ -573,12 +573,15 @@ const initialize = (botToken: string, options: Partial { }; -const validateTakeSellOrder = async (ctx: MainContext, bot: HasTelegram, user: UserDocument, order: IOrder) => { +const validateTakeSellOrder = async (ctx: MainContext, bot: HasTelegram, user: UserDocument, order: IOrder | null) => { try { if (!order) { await messages.invalidOrderMessage(ctx, bot, user); diff --git a/tsconfig.json b/tsconfig.json index ecc59192..63ff67a6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,13 +1,12 @@ { "compilerOptions": { - "strict": false, + "strict": true, "esModuleInterop": true, "resolveJsonModule": true, "downlevelIteration": true, "lib":["ES2021", "DOM"], "outDir": "./dist", "rootDir": ".", - "allowJs": true, "moduleResolution": "node" }, "include": [ diff --git a/util/index.ts b/util/index.ts index 8f467e9b..b1ca0e85 100644 --- a/util/index.ts +++ b/util/index.ts @@ -589,7 +589,7 @@ const generateRandomImage = async (nonce: string) => { if (!wasHoneybadgerSelected) { const files = await fs.readdir('images'); - const imageFiles = files.filter(file => + const imageFiles = files.filter((file: string) => ['.png'].includes(path.extname(file).toLowerCase()) && file !== honeybadgerFilename ); @@ -609,7 +609,7 @@ const generateRandomImage = async (nonce: string) => { return { randomImage, isGoldenHoneyBadger }; }; -const generateQRWithImage = async (request, randomImage) => { +const generateQRWithImage = async (request: string, randomImage: string) => { const canvas = createCanvas(400, 400); await QRCode.toCanvas(canvas, request, { margin: 2,