From d7d07e14903baa7f2233d42cf41268a7951b6702 Mon Sep 17 00:00:00 2001 From: Mehrshad Date: Thu, 31 Aug 2023 17:32:51 +0330 Subject: [PATCH] WIP1-4 --- app.js => app.ts | 18 +- bot/messages.ts | 6 +- bot/start.ts | 17 +- bot/{validations.js => validations.ts} | 97 ++++++----- db_connect.js => db_connect.ts | 9 +- ...ngs.js => calculate_community_earnings.ts} | 8 +- jobs/{cancel_orders.js => cancel_orders.ts} | 11 +- jobs/{communities.js => communities.ts} | 11 +- ...d_orders.js => delete_published_orders.ts} | 11 +- jobs/{node_info.js => node_info.ts} | 9 +- jobs/pending_payments.ts | 2 +- ln/{connect.js => connect.ts} | 10 +- ln/{hold_invoice.js => hold_invoice.ts} | 22 +-- ln/info.js | 13 -- ln/info.ts | 11 ++ ln/{pay_request.js => pay_request.ts} | 34 ++-- ...be_invoices.js => resubscribe_invoices.ts} | 14 +- ...scribe_invoice.js => subscribe_invoice.ts} | 10 +- lnurl/{lnurl-pay.js => lnurl-pay.ts} | 15 +- logger.js => logger.ts | 10 +- package-lock.json | 154 ++++++++++++++++++ package.json | 8 + tests/bot_test.js | 2 +- tsconfig.json | 2 + 24 files changed, 358 insertions(+), 146 deletions(-) rename app.js => app.ts (69%) rename bot/{validations.js => validations.ts} (79%) rename db_connect.js => db_connect.ts (72%) rename jobs/{calculate_community_earnings.js => calculate_community_earnings.ts} (86%) rename jobs/{cancel_orders.js => cancel_orders.ts} (92%) rename jobs/{communities.js => communities.ts} (77%) rename jobs/{delete_published_orders.js => delete_published_orders.ts} (79%) rename jobs/{node_info.js => node_info.ts} (66%) rename ln/{connect.js => connect.ts} (89%) rename ln/{hold_invoice.js => hold_invoice.ts} (63%) delete mode 100644 ln/info.js create mode 100644 ln/info.ts rename ln/{pay_request.js => pay_request.ts} (78%) rename ln/{resubscribe_invoices.js => resubscribe_invoices.ts} (70%) rename ln/{subscribe_invoice.js => subscribe_invoice.ts} (93%) rename lnurl/{lnurl-pay.js => lnurl-pay.ts} (77%) rename logger.js => logger.ts (82%) diff --git a/app.js b/app.ts similarity index 69% rename from app.js rename to app.ts index 2fbc6604..3db3da54 100644 --- a/app.js +++ b/app.ts @@ -1,9 +1,10 @@ -require('dotenv').config(); -const { SocksProxyAgent } = require('socks-proxy-agent'); -const { start } = require('./bot'); -const mongoConnect = require('./db_connect'); +import * as dotenv from "dotenv"; +dotenv.config() +import { SocksProxyAgent } from "socks-proxy-agent"; +import { start } from "./bot/start"; +import mongoConnect from './db_connect' const { resubscribeInvoices } = require('./ln'); -const logger = require('./logger'); +import logger from "./logger"; const { delay } = require('./util'); (async () => { @@ -30,12 +31,13 @@ const { delay } = require('./util'); telegram: { agent, }, - }; + } as any; } - const bot = start(process.env.BOT_TOKEN, options); + const bot = start(String(process.env.BOT_TOKEN), options); // Wait 1 seconds before try to resubscribe hold invoices await delay(1000); await resubscribeInvoices(bot); }) - .on('error', error => logger.error(`Error connecting to Mongo: ${error}`)); + .on('error', (error: Error) => logger.error(`Error connecting to Mongo: ${error}`)); })(); + diff --git a/bot/messages.ts b/bot/messages.ts index 682e9be6..ab50cf97 100644 --- a/bot/messages.ts +++ b/bot/messages.ts @@ -1,5 +1,5 @@ -const { TelegramError } = require('telegraf'); -const QR = require('qrcode'); +import { TelegramError } from 'telegraf' +import QR from 'qrcode'; const { getCurrency, numberFormat, @@ -12,7 +12,7 @@ const { decimalRound, getUserAge, } = require('../util'); -const logger = require('../logger'); +import logger from "../logger"; import { MainContext } from './start'; import { UserDocument } from '../models/user' import { IOrder } from '../models/order' diff --git a/bot/start.ts b/bot/start.ts index 72c6cec2..34bac772 100644 --- a/bot/start.ts +++ b/bot/start.ts @@ -3,9 +3,8 @@ import { I18n, I18nContext } from '@grammyjs/i18n'; import { Message } from 'typegram' import { UserDocument } from '../models/user' import { FilterQuery } from 'mongoose'; - -const { limit } = require('@grammyjs/ratelimiter'); -const schedule = require('node-schedule'); +import { limit } from "@grammyjs/ratelimiter" +import schedule from 'node-schedule'; const { Order, User, @@ -66,7 +65,7 @@ const { deleteCommunity, nodeInfo, } = require('../jobs'); -const logger = require('../logger'); +import logger from "../logger"; export interface MainContext extends Context { match: Array | null; @@ -75,7 +74,7 @@ export interface MainContext extends Context { admin: UserDocument; } -interface OrderQuery { +export interface OrderQuery { status?: string; buyer_id?: string; seller_id?: string; @@ -137,7 +136,7 @@ has the same condition. The problem mentioned above is similar to this issue: https://github.com/telegraf/telegraf/issues/1319#issuecomment-766360594 */ -const ctxUpdateAssertMsg = "ctx.update.message.text is not available."; +export const ctxUpdateAssertMsg = "ctx.update.message.text is not available."; const initialize = (botToken: string, options: Partial>): Telegraf => { const i18n = new I18n({ @@ -256,7 +255,7 @@ const initialize = (botToken: string, options: Partial el); + const [command, orderId] = params.filter((el: string) => el); if (!orderId) { const orders = await askForConfirmation(ctx.user, command); @@ -347,7 +346,7 @@ const initialize = (botToken: string, options: Partial el); + const [command, orderId] = params.filter((el: string) => el); if (!orderId) { const orders = await askForConfirmation(ctx.user, command); @@ -515,7 +514,7 @@ const initialize = (botToken: string, options: Partial el); + const [command, orderId] = params.filter((el: string) => el); if (!orderId) { const orders = await askForConfirmation(ctx.user, command); diff --git a/bot/validations.js b/bot/validations.ts similarity index 79% rename from bot/validations.js rename to bot/validations.ts index a3288bd2..57eb2a28 100644 --- a/bot/validations.js +++ b/bot/validations.ts @@ -1,3 +1,10 @@ +import { MainContext, OrderQuery, ctxUpdateAssertMsg } from "./start"; +import { ICommunity } from "../models/community"; +import { FilterQuery } from "mongoose"; +import { UserDocument } from "../models/user"; +import { IOrder } from "../models/order"; +import { Telegraf } from "telegraf"; + const { parsePaymentRequest } = require('invoices'); const { ObjectId } = require('mongoose').Types; const messages = require('./messages'); @@ -8,11 +15,18 @@ const logger = require('../logger'); // We look in database if the telegram user exists, // if not, it creates a new user -const validateUser = async (ctx, start) => { +const validateUser = async (ctx: MainContext, start: boolean) => { try { - const tgUser = ctx.update.callback_query - ? ctx.update.callback_query.from - : ctx.update.message.from; + let tgUser = null + if (("callback_query" in ctx.update) && ctx.update.callback_query) { + tgUser = ctx.update.callback_query.from + } + else if (("message" in ctx.update) && ctx.update.message) { + tgUser = ctx.update.message.from + } + else { + throw new Error(ctxUpdateAssertMsg); + } // We need to make sure the user has a username if (!tgUser.username) { return await messages.nonHandleErrorMessage(ctx); @@ -45,8 +59,11 @@ const validateUser = async (ctx, start) => { } }; -const validateSuperAdmin = async (ctx, id) => { +const validateSuperAdmin = async (ctx: MainContext, id?: string) => { // id is UNKNOWN & not used try { + if (!('message' in ctx.update) || !('text' in ctx.update.message)) { + throw new Error(ctxUpdateAssertMsg); + } const tgUserId = id || ctx.update.message.from.id; const user = await User.findOne({ tg_id: tgUserId }); // If the user never started the bot we can't send messages @@ -62,8 +79,11 @@ const validateSuperAdmin = async (ctx, id) => { } }; -const validateAdmin = async (ctx, id) => { +const validateAdmin = async (ctx: MainContext, id?: string) => { // id is UNKNOWN & not used try { + if (!('message' in ctx.update) || !('text' in ctx.update.message)) { + throw new Error(ctxUpdateAssertMsg); + } const tgUserId = id || ctx.update.message.from.id; const user = await User.findOne({ tg_id: tgUserId }); // If the user never started the bot we can't send messages @@ -86,7 +106,7 @@ const validateAdmin = async (ctx, id) => { } }; -const validateSellOrder = async ctx => { +const validateSellOrder = async (ctx: MainContext) => { try { const args = ctx.state.command.args; if (args.length < 4) { @@ -130,7 +150,7 @@ const validateSellOrder = async ctx => { return false; } - if (amount !== 0 && amount < process.env.MIN_PAYMENT_AMT) { + if (amount !== 0 && amount < Number(process.env.MIN_PAYMENT_AMT)) { await messages.mustBeGreatherEqThan( ctx, 'monto_en_sats', @@ -149,7 +169,7 @@ const validateSellOrder = async ctx => { return false; } - if (fiatAmount.some(x => x < 1)) { + if (fiatAmount.some((x: number) => x < 1)) { await messages.mustBeGreatherEqThan(ctx, 'monto_en_fiat', 1); return false; } @@ -174,7 +194,7 @@ const validateSellOrder = async ctx => { } }; -const validateBuyOrder = async ctx => { +const validateBuyOrder = async (ctx: MainContext) => { try { const args = ctx.state.command.args; if (args.length < 4) { @@ -216,7 +236,7 @@ const validateBuyOrder = async ctx => { return false; } - if (amount !== 0 && amount < process.env.MIN_PAYMENT_AMT) { + if (amount !== 0 && amount < Number(process.env.MIN_PAYMENT_AMT)) { await messages.mustBeGreatherEqThan( ctx, 'monto_en_sats', @@ -235,7 +255,7 @@ const validateBuyOrder = async ctx => { return false; } - if (fiatAmount.some(x => x < 1)) { + if (fiatAmount.some((x: number) => x < 1)) { await messages.mustBeGreatherEqThan(ctx, 'monto_en_fiat', 1); return false; } @@ -259,7 +279,7 @@ const validateBuyOrder = async ctx => { return false; } }; -const validateLightningAddress = async lightningAddress => { +const validateLightningAddress = async (lightningAddress: string) => { const pattern = /^[\w-.]+@([\w-]+.)+[\w-]{2,4}$/g; return ( @@ -267,18 +287,18 @@ const validateLightningAddress = async lightningAddress => { ); }; -const validateInvoice = async (ctx, lnInvoice) => { +const validateInvoice = async (ctx: MainContext, lnInvoice: string) => { try { const invoice = parsePaymentRequest({ request: lnInvoice }); const latestDate = new Date( - Date.now() + parseInt(process.env.INVOICE_EXPIRATION_WINDOW) + Date.now() + Number(process.env.INVOICE_EXPIRATION_WINDOW) ).toISOString(); - if (!!invoice.tokens && invoice.tokens < process.env.MIN_PAYMENT_AMT) { + if (!!invoice.tokens && invoice.tokens < Number(process.env.MIN_PAYMENT_AMT)) { await messages.minimunAmountInvoiceMessage(ctx); return false; } - if (new Date(invoice.expires_at) < latestDate) { + if (new Date(invoice.expires_at).toISOString() < latestDate) { await messages.minimunExpirationTimeInvoiceMessage(ctx); return false; } @@ -306,20 +326,20 @@ const validateInvoice = async (ctx, lnInvoice) => { } }; -const isValidInvoice = async (ctx, lnInvoice) => { +const isValidInvoice = async (ctx: MainContext, lnInvoice: string) => { try { const invoice = parsePaymentRequest({ request: lnInvoice }); const latestDate = new Date( - Date.now() + parseInt(process.env.INVOICE_EXPIRATION_WINDOW) + Date.now() + Number(process.env.INVOICE_EXPIRATION_WINDOW) ).toISOString(); - if (!!invoice.tokens && invoice.tokens < process.env.MIN_PAYMENT_AMT) { + if (!!invoice.tokens && invoice.tokens < Number(process.env.MIN_PAYMENT_AMT)) { await messages.invoiceMustBeLargerMessage(ctx); return { success: false, }; } - if (new Date(invoice.expires_at) < latestDate) { + if (new Date(invoice.expires_at).toISOString() < latestDate) { await messages.invoiceExpiryTooShortMessage(ctx); return { success: false, @@ -359,7 +379,7 @@ const isValidInvoice = async (ctx, lnInvoice) => { } }; -const isOrderCreator = (user, order) => { +const isOrderCreator = (user: UserDocument, order: IOrder) => { try { return user._id == order.creator_id; } catch (error) { @@ -368,7 +388,7 @@ const isOrderCreator = (user, order) => { } }; -const validateTakeSellOrder = async (ctx, bot, user, order) => { +const validateTakeSellOrder = async (ctx: MainContext, bot: Telegraf, user: UserDocument, order: IOrder) => { try { if (!order) { await messages.invalidOrderMessage(ctx, bot, user); @@ -397,7 +417,7 @@ const validateTakeSellOrder = async (ctx, bot, user, order) => { } }; -const validateTakeBuyOrder = async (ctx, bot, user, order) => { +const validateTakeBuyOrder = async (ctx: MainContext, bot: Telegraf, user: UserDocument, order: IOrder) => { try { if (!order) { await messages.invalidOrderMessage(bot, user); @@ -422,9 +442,9 @@ const validateTakeBuyOrder = async (ctx, bot, user, order) => { } }; -const validateReleaseOrder = async (ctx, user, orderId) => { +const validateReleaseOrder = async (ctx: MainContext, user: UserDocument, orderId: string) => { try { - let where = { + let where: FilterQuery = { seller_id: user._id, status: 'WAITING_BUYER_INVOICE', _id: orderId, @@ -465,7 +485,7 @@ const validateReleaseOrder = async (ctx, user, orderId) => { } }; -const validateDisputeOrder = async (ctx, user, orderId) => { +const validateDisputeOrder = async (ctx: MainContext, user: UserDocument, orderId: string) => { try { const where = { $and: [ @@ -489,9 +509,9 @@ const validateDisputeOrder = async (ctx, user, orderId) => { } }; -const validateFiatSentOrder = async (ctx, user, orderId) => { +const validateFiatSentOrder = async (ctx: MainContext, user: UserDocument, orderId: string) => { try { - const where = { + const where: FilterQuery = { $and: [ { buyer_id: user._id }, { $or: [{ status: 'ACTIVE' }, { status: 'PAID_HOLD_INVOICE' }] }, @@ -525,7 +545,7 @@ const validateFiatSentOrder = async (ctx, user, orderId) => { }; // If a seller have an order with status FIAT_SENT, return false -const validateSeller = async (ctx, user) => { +const validateSeller = async (ctx: MainContext, user: UserDocument) => { try { const where = { seller_id: user._id, @@ -546,10 +566,13 @@ const validateSeller = async (ctx, user) => { } }; -const validateParams = async (ctx, paramNumber, errOutputString) => { +const validateParams = async (ctx: MainContext, paramNumber: number, errOutputString: string) => { try { + if (!('message' in ctx.update) || !('text' in ctx.update.message)) { + throw new Error(ctxUpdateAssertMsg); + } const paramsArray = ctx.update.message.text.split(' '); - const params = paramsArray.filter(el => el !== ''); + const params = paramsArray.filter((el: string) => el !== ''); if (params.length !== paramNumber) { await messages.customMessage( ctx, @@ -566,7 +589,7 @@ const validateParams = async (ctx, paramNumber, errOutputString) => { } }; -const validateObjectId = async (ctx, id) => { +const validateObjectId = async (ctx: MainContext, id: string) => { try { if (!ObjectId.isValid(id)) { await messages.notValidIdMessage(ctx); @@ -580,10 +603,10 @@ const validateObjectId = async (ctx, id) => { } }; -const validateUserWaitingOrder = async (ctx, bot, user) => { +const validateUserWaitingOrder = async (ctx: MainContext, bot: Telegraf, user: UserDocument) => { try { // If is a seller - let where = { + let where: FilterQuery = { seller_id: user._id, status: 'WAITING_PAYMENT', }; @@ -610,12 +633,12 @@ const validateUserWaitingOrder = async (ctx, bot, user) => { }; // We check if the user is banned from the community in the order -const isBannedFromCommunity = async (user, communityId) => { +const isBannedFromCommunity = async (user: UserDocument, communityId: string) => { try { if (!communityId) return false; const community = await Community.findOne({ _id: communityId }); if (!community) return false; - return community.banned_users.some(buser => buser.id == user._id); + return community.banned_users.some((buser: ICommunity) => buser.id == user._id); } catch (error) { logger.error(error); return false; diff --git a/db_connect.js b/db_connect.ts similarity index 72% rename from db_connect.js rename to db_connect.ts index e38fbd10..1353b6f0 100644 --- a/db_connect.js +++ b/db_connect.ts @@ -1,5 +1,5 @@ -const mongoose = require('mongoose'); -const logger = require('./logger'); +import mongoose from "mongoose"; +import logger from "./logger"; // connect to database const credentials = process.env.DB_USER @@ -12,12 +12,13 @@ if (!MONGO_URI) { throw new Error('You must provide a MongoDB URI'); } logger.info(`Connecting to: ${MONGO_URI}`); +// TODO: Update mongoose to latest version const connect = () => { mongoose.connect(MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true, - }); + } as any); // older version of mongoose that does not have the ConnectOptions type defined. return mongoose; }; -module.exports = connect; +export default connect; diff --git a/jobs/calculate_community_earnings.js b/jobs/calculate_community_earnings.ts similarity index 86% rename from jobs/calculate_community_earnings.js rename to jobs/calculate_community_earnings.ts index 56151d48..d394a922 100644 --- a/jobs/calculate_community_earnings.js +++ b/jobs/calculate_community_earnings.ts @@ -1,5 +1,5 @@ const { Order, Community } = require('../models'); -const logger = require('../logger'); +import logger from "../logger"; const calculateEarnings = async () => { try { @@ -12,9 +12,9 @@ const calculateEarnings = async () => { for (const order of orders) { const amount = order.amount; const fee = order.fee; - const botFee = order.bot_fee || parseFloat(process.env.MAX_FEE); + const botFee = order.bot_fee || Number(process.env.MAX_FEE); const communityFeePercent = - order.community_fee || parseFloat(process.env.FEE_PERCENT); + order.community_fee || Number(process.env.FEE_PERCENT); const maxFee = amount * botFee; const communityFee = fee - maxFee * communityFeePercent; const earnings = earningsMap.get(order.community_id) || [0, 0]; @@ -36,7 +36,7 @@ const calculateEarnings = async () => { ); } } catch (error) { - const message = error.toString(); + const message = String(error); logger.error(`calculateEarnings catch error: ${message}`); } }; diff --git a/jobs/cancel_orders.js b/jobs/cancel_orders.ts similarity index 92% rename from jobs/cancel_orders.js rename to jobs/cancel_orders.ts index 00cef019..01c2739b 100644 --- a/jobs/cancel_orders.js +++ b/jobs/cancel_orders.ts @@ -1,15 +1,18 @@ +import { Telegraf } from "telegraf"; +import { MainContext } from "../bot/start"; + const { User, Order } = require('../models'); const { cancelShowHoldInvoice, cancelAddInvoice } = require('../bot/commands'); const messages = require('../bot/messages'); const { getUserI18nContext, holdInvoiceExpirationInSecs } = require('../util'); -const logger = require('../logger'); +import logger from "../logger"; -const cancelOrders = async bot => { +const cancelOrders = async (bot: Telegraf) => { try { const holdInvoiceTime = new Date(); holdInvoiceTime.setSeconds( holdInvoiceTime.getSeconds() - - parseInt(process.env.HOLD_INVOICE_EXPIRATION_WINDOW) + Number(process.env.HOLD_INVOICE_EXPIRATION_WINDOW) ); // We get the orders where the seller didn't pay the hold invoice before expired // or where the buyer didn't add the invoice @@ -70,7 +73,7 @@ const cancelOrders = async bot => { // Now we cancel orders expired // ============================== orderTime = new Date(); - let orderExpirationTime = parseInt( + let orderExpirationTime = Number( process.env.ORDER_PUBLISHED_EXPIRATION_WINDOW ); orderExpirationTime = orderExpirationTime + orderExpirationTime * 0.2; diff --git a/jobs/communities.js b/jobs/communities.ts similarity index 77% rename from jobs/communities.js rename to jobs/communities.ts index e9ddb503..026a6446 100644 --- a/jobs/communities.js +++ b/jobs/communities.ts @@ -1,12 +1,15 @@ +import { Telegraf } from "telegraf"; +import { MainContext } from "../bot/start"; + const { Order, Community } = require('../models'); -const logger = require('../logger'); +import logger from "../logger"; -const deleteCommunity = async bot => { +const deleteCommunity = async (bot: Telegraf) => { try { const communities = await Community.find(); for (const community of communities) { // Delete communities with COMMUNITY_TTL days without a successful order - const days = 86400 * parseInt(process.env.COMMUNITY_TTL); + const days = 86400 * Number(process.env.COMMUNITY_TTL); const time = new Date(); time.setSeconds(time.getSeconds() - days); // If is a new community we don't do anything @@ -26,7 +29,7 @@ const deleteCommunity = async bot => { } } } catch (error) { - const message = error.toString(); + const message = String(error); logger.error(`deleteCommunity catch error: ${message}`); } }; diff --git a/jobs/delete_published_orders.js b/jobs/delete_published_orders.ts similarity index 79% rename from jobs/delete_published_orders.js rename to jobs/delete_published_orders.ts index b4e284ae..d16dc1e4 100644 --- a/jobs/delete_published_orders.js +++ b/jobs/delete_published_orders.ts @@ -1,13 +1,16 @@ +import { Telegraf } from "telegraf"; +import { MainContext } from "../bot/start"; + const { Order } = require('../models'); const { deleteOrderFromChannel } = require('../util'); -const logger = require('../logger'); +import logger from "../logger"; -const deleteOrders = async bot => { +const deleteOrders = async (bot: Telegraf) => { try { const windowTime = new Date(); windowTime.setSeconds( windowTime.getSeconds() - - parseInt(process.env.ORDER_PUBLISHED_EXPIRATION_WINDOW) + Number(process.env.ORDER_PUBLISHED_EXPIRATION_WINDOW) ); // We get the pending orders where time is expired const pendingOrders = await Order.find({ @@ -25,7 +28,7 @@ const deleteOrders = async bot => { await deleteOrderFromChannel(orderCloned, bot.telegram); } } catch (error) { - const message = error.toString(); + const message = String(error); logger.error(`deleteOrders catch error: ${message}`); } }; diff --git a/jobs/node_info.js b/jobs/node_info.ts similarity index 66% rename from jobs/node_info.js rename to jobs/node_info.ts index bad5d904..d0dce4ce 100644 --- a/jobs/node_info.js +++ b/jobs/node_info.ts @@ -1,8 +1,11 @@ +import { Telegraf } from "telegraf"; +import { MainContext } from "../bot/start"; + const { Config } = require('../models'); const { getInfo } = require('../ln'); -const logger = require('../logger'); +import logger from "../logger"; -const info = async bot => { +const info = async (bot: Telegraf) => { try { const config = await Config.findOne({}); const info = await getInfo(); @@ -12,7 +15,7 @@ const info = async bot => { config.node_uri = info.uris[0]; await config.save(); } catch (error) { - const message = error.toString(); + const message = String(error); logger.error(`node info catch error: ${message}`); } }; diff --git a/jobs/pending_payments.ts b/jobs/pending_payments.ts index 80b79135..fd292313 100644 --- a/jobs/pending_payments.ts +++ b/jobs/pending_payments.ts @@ -2,7 +2,7 @@ const { payRequest, isPendingPayment } = require('../ln'); const { PendingPayment, Order, User, Community } = require('../models'); const messages = require('../bot/messages'); const { getUserI18nContext } = require('../util'); -const logger = require('../logger'); +import logger from "../logger"; import { Telegraf } from 'telegraf'; import { I18nContext } from '@grammyjs/i18n'; import { MainContext } from '../bot/start'; diff --git a/ln/connect.js b/ln/connect.ts similarity index 89% rename from ln/connect.js rename to ln/connect.ts index 167d5445..f82b5c04 100644 --- a/ln/connect.js +++ b/ln/connect.ts @@ -1,7 +1,7 @@ -const fs = require('fs'); -const path = require('path'); -const lightning = require('lightning'); -const logger = require('../logger'); +import * as fs from 'fs'; +import * as path from 'path'; +import * as lightning from "lightning"; +import logger from "../logger"; const { authenticatedLndGrpc } = lightning; @@ -47,4 +47,4 @@ const { lnd } = authenticatedLndGrpc({ socket, }); -module.exports = lnd; +export { lnd }; diff --git a/ln/hold_invoice.js b/ln/hold_invoice.ts similarity index 63% rename from ln/hold_invoice.js rename to ln/hold_invoice.ts index 1a36c39c..9717dfd5 100644 --- a/ln/hold_invoice.js +++ b/ln/hold_invoice.ts @@ -1,26 +1,26 @@ -const { createHash, randomBytes } = require('crypto'); -const lightning = require('lightning'); -const lnd = require('./connect'); -const logger = require('../logger'); +import { randomBytes, createHash } from 'crypto'; +import * as lightning from "lightning"; +import { lnd } from './connect' +import logger from "../logger"; -const createHoldInvoice = async ({ description, amount }) => { +const createHoldInvoice = async (description: string, amount: number ) => { try { const randomSecret = () => randomBytes(32); - const sha256 = buffer => createHash('sha256').update(buffer).digest('hex'); + const sha256 = (buffer: Buffer): string => createHash('sha256').update(buffer).digest('hex'); // We create a random secret const secret = randomSecret(); const expiresAt = new Date(); expiresAt.setSeconds(expiresAt.getSeconds() + 3600); const hash = sha256(secret); - const cltv_delta = parseInt(process.env.HOLD_INVOICE_CLTV_DELTA); + const cltv_delta = Number(process.env.HOLD_INVOICE_CLTV_DELTA); const { request, id } = await lightning.createHodlInvoice({ cltv_delta, lnd, description, id: hash, tokens: amount, - expires_at: expiresAt, + expires_at: expiresAt.toISOString(), }); // We sent back the response hash (id) to be used on testing @@ -30,7 +30,7 @@ const createHoldInvoice = async ({ description, amount }) => { } }; -const settleHoldInvoice = async ({ secret }) => { +const settleHoldInvoice = async ( secret: string ) => { try { await lightning.settleHodlInvoice({ lnd, secret }); } catch (error) { @@ -38,7 +38,7 @@ const settleHoldInvoice = async ({ secret }) => { } }; -const cancelHoldInvoice = async ({ hash }) => { +const cancelHoldInvoice = async ( hash: string ) => { try { await lightning.cancelHodlInvoice({ lnd, id: hash }); } catch (error) { @@ -46,7 +46,7 @@ const cancelHoldInvoice = async ({ hash }) => { } }; -const getInvoice = async ({ hash }) => { +const getInvoice = async ( hash: string ) => { try { return await lightning.getInvoice({ lnd, id: hash }); } catch (error) { diff --git a/ln/info.js b/ln/info.js deleted file mode 100644 index da731135..00000000 --- a/ln/info.js +++ /dev/null @@ -1,13 +0,0 @@ -const lightning = require('lightning'); -const lnd = require('./connect'); -const logger = require('../logger'); - -const getInfo = async () => { - try { - return await lightning.getWalletInfo({ lnd }); - } catch (error) { - logger.error(error); - } -}; - -module.exports = { getInfo }; diff --git a/ln/info.ts b/ln/info.ts new file mode 100644 index 00000000..179fb82e --- /dev/null +++ b/ln/info.ts @@ -0,0 +1,11 @@ +import * as lightning from "lightning"; +import { lnd } from './connect' +import logger from "../logger"; + +export const getInfo = async () => { + try { + return await lightning.getWalletInfo({ lnd }); + } catch (error) { + logger.error(error); + } +}; diff --git a/ln/pay_request.js b/ln/pay_request.ts similarity index 78% rename from ln/pay_request.js rename to ln/pay_request.ts index 59fe6d38..8f3afc5f 100644 --- a/ln/pay_request.js +++ b/ln/pay_request.ts @@ -1,16 +1,20 @@ -const { +import { AuthenticatedLnd } from "lightning"; +import { Telegraf } from "telegraf"; +import { MainContext } from "../bot/start"; +import { IOrder } from "../models/order"; +import { payViaPaymentRequest, getPayment, - deleteForwardingReputations, -} = require('lightning'); + deleteForwardingReputations +} from "lightning"; const { parsePaymentRequest } = require('invoices'); const { User, PendingPayment } = require('../models'); -const lnd = require('./connect'); +import { lnd } from "./connect"; const { handleReputationItems, getUserI18nContext } = require('../util'); const messages = require('../bot/messages'); -const logger = require('../logger'); +import logger from "../logger"; -const payRequest = async ({ request, amount }) => { +const payRequest = async ({ request, amount }: { request: string; amount: number }) => { try { const invoice = parsePaymentRequest({ request }); if (!invoice) return false; @@ -18,9 +22,17 @@ const payRequest = async ({ request, amount }) => { if (invoice.is_expired) return invoice; // We need to set a max fee amount - const maxFee = amount * parseFloat(process.env.MAX_ROUTING_FEE); + const maxFee = amount * Number(process.env.MAX_ROUTING_FEE); - const params = { + type Params = { + lnd: AuthenticatedLnd; + request: string; + pathfinding_timeout: number; + max_fee?: number; // optional property + tokens?: number; // optional property + }; + + const params: Params = { lnd, request, pathfinding_timeout: 60000, @@ -44,7 +56,7 @@ const payRequest = async ({ request, amount }) => { } }; -const payToBuyer = async (bot, order) => { +const payToBuyer = async (bot: Telegraf, order: IOrder) => { try { // We check if the payment is on flight we don't do anything const isPending = await isPendingPayment(order.buyer_invoice); @@ -99,14 +111,14 @@ const payToBuyer = async (bot, order) => { } }; -const isPendingPayment = async request => { +const isPendingPayment = async (request: string) => { try { const { id } = parsePaymentRequest({ request }); const { is_pending } = await getPayment({ lnd, id }); return !!is_pending; } catch (error) { - const message = error.toString(); + const message = String(error); logger.error(`isPendingPayment catch error: ${message}`); return false; } diff --git a/ln/resubscribe_invoices.js b/ln/resubscribe_invoices.ts similarity index 70% rename from ln/resubscribe_invoices.js rename to ln/resubscribe_invoices.ts index 644dbbba..8fa91527 100644 --- a/ln/resubscribe_invoices.js +++ b/ln/resubscribe_invoices.ts @@ -1,13 +1,15 @@ -const { getInvoices } = require('lightning'); -const lnd = require('./connect'); +import { Telegraf } from 'telegraf'; +import { MainContext } from "../bot/start"; +import { getInvoices, GetInvoicesResult } from 'lightning'; +import { lnd } from './connect'; const subscribeInvoice = require('./subscribe_invoice'); const { Order } = require('../models'); -const logger = require('../logger'); +import logger from "../logger"; -const resubscribeInvoices = async bot => { +const resubscribeInvoices = async (bot: Telegraf) => { try { let invoicesReSubscribed = 0; - const isHeld = invoice => !!invoice.is_held; + const isHeld = (invoice: any) => !!invoice.is_held; const unconfirmedInvoices = ( await getInvoices({ lnd, @@ -29,7 +31,7 @@ const resubscribeInvoices = async bot => { } logger.info(`Invoices resubscribed: ${invoicesReSubscribed}`); } catch (error) { - logger.error(`ResuscribeInvoice catch: ${error.toString()}`); + logger.error(`ResuscribeInvoice catch: ${String(error)}`); return false; } }; diff --git a/ln/subscribe_invoice.js b/ln/subscribe_invoice.ts similarity index 93% rename from ln/subscribe_invoice.js rename to ln/subscribe_invoice.ts index 2f96e36a..bcdc82ad 100644 --- a/ln/subscribe_invoice.js +++ b/ln/subscribe_invoice.ts @@ -1,13 +1,15 @@ -const { subscribeToInvoice } = require('lightning'); +import { Telegraf } from "telegraf"; +import { MainContext } from "../bot/start"; +import {subscribeToInvoice} from 'lightning' const { Order, User } = require('../models'); const { payToBuyer } = require('./pay_request'); -const lnd = require('./connect'); +import { lnd } from "./connect"; const messages = require('../bot/messages'); const ordersActions = require('../bot/ordersActions'); const { getUserI18nContext, getEmojiRate, decimalRound } = require('../util'); -const logger = require('../logger'); +import logger from "../logger"; -const subscribeInvoice = async (bot, id, resub) => { +const subscribeInvoice = async (bot: Telegraf, id: string, resub: boolean) => { try { const sub = subscribeToInvoice({ id, lnd }); sub.on('invoice_updated', async invoice => { diff --git a/lnurl/lnurl-pay.js b/lnurl/lnurl-pay.ts similarity index 77% rename from lnurl/lnurl-pay.js rename to lnurl/lnurl-pay.ts index 45235898..4ebc2e99 100644 --- a/lnurl/lnurl-pay.js +++ b/lnurl/lnurl-pay.ts @@ -1,11 +1,11 @@ -const axios = require('axios').default; -const logger = require('../logger'); +import axios from 'axios'; +import logger from "../logger"; // { // pr: String, // bech32-serialized lightning invoice // routes: [], // an empty array // } -const resolvLightningAddress = async (address, amountMsat) => { +const resolvLightningAddress = async (address: string, amountMsat: number) => { const [user, domain] = address.split('@'); const lnAddressQuery = `https://${domain}/.well-known/lnurlp/${user}`; @@ -17,7 +17,7 @@ const resolvLightningAddress = async (address, amountMsat) => { } if ( - (lnAddressRes.minSendable > amountMsat) | + (lnAddressRes.minSendable > amountMsat) || (lnAddressRes.maxSendable < amountMsat) ) { logger.info('lnAddress invalid amount'); @@ -31,7 +31,7 @@ const resolvLightningAddress = async (address, amountMsat) => { return res; }; -const existLightningAddress = async address => { +const existLightningAddress = async (address: string) => { const [user, domain] = address.split('@'); const lnAddressQuery = `https://${domain}/.well-known/lnurlp/${user}`; @@ -49,7 +49,4 @@ const existLightningAddress = async address => { } }; -module.exports = { - resolvLightningAddress, - existLightningAddress, -}; +export { resolvLightningAddress, existLightningAddress } diff --git a/logger.js b/logger.ts similarity index 82% rename from logger.js rename to logger.ts index ada7ed8e..d5fe6e2a 100644 --- a/logger.js +++ b/logger.ts @@ -1,4 +1,4 @@ -const winston = require('winston'); +import * as winston from 'winston'; const level = process.env.LOG_LEVEL || 'notice'; @@ -9,9 +9,8 @@ const logger = winston.createLogger({ }), winston.format.colorize(), winston.format.printf(info => { - return `[${info.timestamp}] ${info.level}: ${info.message} ${ - info.stack ? info.stack : '' - }`; + return `[${info.timestamp}] ${info.level}: ${info.message} ${info.stack ? info.stack : '' + }`; }) ), levels: winston.config.syslog.levels, @@ -24,4 +23,5 @@ const logger = winston.createLogger({ exitOnError: false, }); -module.exports = logger; + +export default logger; diff --git a/package-lock.json b/package-lock.json index c7e08854..6a29f090 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,15 @@ "winston": "^3.7.2" }, "devDependencies": { + "@types/chai": "^4.3.6", + "@types/eslint": "^8.44.2", + "@types/eslint-config-prettier": "^6.11.0", + "@types/mocha": "^10.0.1", "@types/node": "^20.5.0", + "@types/node-schedule": "^2.1.0", + "@types/nodemon": "1.19.2", + "@types/prettier": "^2.7.3", + "@types/qrcode": "^1.5.2", "chai": "^4.3.4", "chokidar": "^3.5.3", "eslint": "^8.15.0", @@ -1584,6 +1592,12 @@ "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==" }, + "node_modules/@types/chai": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.6.tgz", + "integrity": "sha512-VOVRLM1mBxIRxydiViqPcKn6MIxZytrbMpd6RJLIWKxUNr3zux8no0Oc7kJx0WAPIitgZ0gkrDS+btlqQpubpw==", + "dev": true + }, "node_modules/@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -1592,6 +1606,28 @@ "@types/node": "*" } }, + "node_modules/@types/eslint": { + "version": "8.44.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz", + "integrity": "sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-config-prettier": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@types/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", + "integrity": "sha512-UBuZMZVog9c9jXvArbYtWH570sRWNaU6kEnUAHsHb/+zAufzPT4I+gMkUR2dVPWlqiceoRU1thjUVdGrAWVpCA==", + "dev": true + }, + "node_modules/@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "dev": true + }, "node_modules/@types/express": { "version": "4.17.17", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", @@ -1619,6 +1655,12 @@ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" }, + "node_modules/@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "dev": true + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -1635,11 +1677,50 @@ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, + "node_modules/@types/mocha": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", + "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", + "dev": true + }, "node_modules/@types/node": { "version": "20.5.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz", "integrity": "sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==" }, + "node_modules/@types/node-schedule": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/node-schedule/-/node-schedule-2.1.0.tgz", + "integrity": "sha512-NiTwl8YN3v/1YCKrDFSmCTkVxFDylueEqsOFdgF+vPsm+AlyJKGAo5yzX1FiOxPsZiN6/r8gJitYx2EaSuBmmg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/nodemon": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/nodemon/-/nodemon-1.19.2.tgz", + "integrity": "sha512-4GWiTN3HevkxMIxEQ7OpD3MAHhlVsX2tairCMRmf8oYZxmhHw9+UpQpIdGdJrjsMT2Ty26FtJzUUcP/qM5fR8A==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true + }, + "node_modules/@types/qrcode": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.2.tgz", + "integrity": "sha512-W4KDz75m7rJjFbyCctzCtRzZUj+PrUHV+YjqDp50sSRezTbrtEAIq2iTzC6lISARl3qw+8IlcCyljdcVJE0Wug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", @@ -8406,6 +8487,12 @@ "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==" }, + "@types/chai": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.6.tgz", + "integrity": "sha512-VOVRLM1mBxIRxydiViqPcKn6MIxZytrbMpd6RJLIWKxUNr3zux8no0Oc7kJx0WAPIitgZ0gkrDS+btlqQpubpw==", + "dev": true + }, "@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -8414,6 +8501,28 @@ "@types/node": "*" } }, + "@types/eslint": { + "version": "8.44.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz", + "integrity": "sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-config-prettier": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@types/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", + "integrity": "sha512-UBuZMZVog9c9jXvArbYtWH570sRWNaU6kEnUAHsHb/+zAufzPT4I+gMkUR2dVPWlqiceoRU1thjUVdGrAWVpCA==", + "dev": true + }, + "@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "dev": true + }, "@types/express": { "version": "4.17.17", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", @@ -8441,6 +8550,12 @@ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" }, + "@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "dev": true + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -8457,11 +8572,50 @@ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, + "@types/mocha": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", + "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", + "dev": true + }, "@types/node": { "version": "20.5.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz", "integrity": "sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==" }, + "@types/node-schedule": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/node-schedule/-/node-schedule-2.1.0.tgz", + "integrity": "sha512-NiTwl8YN3v/1YCKrDFSmCTkVxFDylueEqsOFdgF+vPsm+AlyJKGAo5yzX1FiOxPsZiN6/r8gJitYx2EaSuBmmg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/nodemon": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/nodemon/-/nodemon-1.19.2.tgz", + "integrity": "sha512-4GWiTN3HevkxMIxEQ7OpD3MAHhlVsX2tairCMRmf8oYZxmhHw9+UpQpIdGdJrjsMT2Ty26FtJzUUcP/qM5fR8A==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true + }, + "@types/qrcode": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.2.tgz", + "integrity": "sha512-W4KDz75m7rJjFbyCctzCtRzZUj+PrUHV+YjqDp50sSRezTbrtEAIq2iTzC6lISARl3qw+8IlcCyljdcVJE0Wug==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", diff --git a/package.json b/package.json index 3d341914..241c65e2 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,15 @@ "network" ], "devDependencies": { + "@types/chai": "^4.3.6", + "@types/eslint": "^8.44.2", + "@types/eslint-config-prettier": "^6.11.0", + "@types/mocha": "^10.0.1", "@types/node": "^20.5.0", + "@types/node-schedule": "^2.1.0", + "@types/nodemon": "1.19.2", + "@types/prettier": "^2.7.3", + "@types/qrcode": "^1.5.2", "chai": "^4.3.4", "chokidar": "^3.5.3", "eslint": "^8.15.0", diff --git a/tests/bot_test.js b/tests/bot_test.js index df4ceca5..0feb9570 100644 --- a/tests/bot_test.js +++ b/tests/bot_test.js @@ -10,7 +10,7 @@ const ordersActions = require('../bot/ordersActions'); const testUser = require('./user'); const testOrder = require('./order'); const { getCurrenciesWithPrice } = require('../util'); -const mongoConnect = require('../db_connect'); +const mongoConnect = require('../db_connect').default; mongoConnect(); diff --git a/tsconfig.json b/tsconfig.json index 8039f57e..f7ab49dd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,7 @@ { "compilerOptions": { "strict": true, + "downlevelIteration": true, + "esModuleInterop": true } }