From bacff70da76c8898df43ec65843a2cd60e36ee44 Mon Sep 17 00:00:00 2001 From: Mehrshad Date: Mon, 28 Aug 2023 17:33:30 +0330 Subject: [PATCH] WIP --- bot/messages.ts | 85 ++++++++++++++++---------------- models/order.js | 85 -------------------------------- models/order.ts | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+), 127 deletions(-) delete mode 100644 models/order.js create mode 100644 models/order.ts diff --git a/bot/messages.ts b/bot/messages.ts index 43924897..6d1bbf8f 100644 --- a/bot/messages.ts +++ b/bot/messages.ts @@ -15,6 +15,7 @@ const { const logger = require('../logger'); import { MainContext } from './start'; import { UserDocument } from '../models/user' +import { IOrder } from '../models/order' import { Telegraf } from 'telegraf'; import { I18nContext } from '@grammyjs/i18n'; import dotenv from 'dotenv'; @@ -65,7 +66,7 @@ const invoicePaymentRequestMessage = async ( ctx: MainContext, user: UserDocument, request, - order, + order: IOrder, i18n: I18nContext, buyer: UserDocument ) => { @@ -108,7 +109,7 @@ const invoicePaymentRequestMessage = async ( } }; -const pendingSellMessage = async (ctx: MainContext, user: UserDocument, order, channel: string, i18n: I18nContext) => { +const pendingSellMessage = async (ctx: MainContext, user: UserDocument, order: IOrder, channel: string, i18n: I18nContext) => { try { const orderExpirationWindow = process.env.ORDER_PUBLISHED_EXPIRATION_WINDOW / 60 / 60; @@ -129,7 +130,7 @@ const pendingSellMessage = async (ctx: MainContext, user: UserDocument, order, c } }; -const pendingBuyMessage = async (bot: Telegraf, user: UserDocument, order, channel: string, i18n: I18nContext) => { +const pendingBuyMessage = async (bot: Telegraf, user: UserDocument, order: IOrder, channel: string, i18n: I18nContext) => { try { const orderExpirationWindow = process.env.ORDER_PUBLISHED_EXPIRATION_WINDOW / 60 / 60; @@ -200,7 +201,7 @@ const expiredInvoiceMessage = async (ctx: MainContext) => { } }; -const expiredInvoiceOnPendingMessage = async (bot: Telegraf, user: UserDocument, order, i18n: I18nContext) => { +const expiredInvoiceOnPendingMessage = async (bot: Telegraf, user: UserDocument, order: IOrder, i18n: I18nContext) => { try { await bot.telegram.sendMessage(user.tg_id, i18n.t('invoice_expired_long')); await bot.telegram.sendMessage( @@ -281,7 +282,7 @@ const invalidOrderMessage = async (ctx: MainContext, bot: Telegraf, } }; -const invalidTypeOrderMessage = async (ctx: MainContext, bot: Telegraf, user: UserDocument, type) => { +const invalidTypeOrderMessage = async (ctx: MainContext, bot: Telegraf, user: UserDocument, type: IOrder["type"]) => { try { await bot.telegram.sendMessage( user.tg_id, @@ -319,7 +320,7 @@ const genericErrorMessage = async (bot: Telegraf, user: UserDocumen } }; -const beginTakeBuyMessage = async (ctx: MainContext, bot: Telegraf, seller: UserDocument, order) => { +const beginTakeBuyMessage = async (ctx: MainContext, bot: Telegraf, seller: UserDocument, order: IOrder) => { try { const expirationTime = parseInt(process.env.HOLD_INVOICE_EXPIRATION_WINDOW) / 60; @@ -352,8 +353,8 @@ const showHoldInvoiceMessage = async ( ctx: MainContext, request, amount: number, - fiatCode, - fiatAmount + fiatCode: IOrder["fiat_code"], + fiatAmount: IOrder["fiat_amount"] ) => { try { let currency = getCurrency(fiatCode); @@ -388,7 +389,7 @@ const onGoingTakeBuyMessage = async ( bot:Telegraf, seller: UserDocument, buyer: UserDocument, - order, + order: IOrder, i18nBuyer: I18nContext, i18nSeller: I18nContext, rate: string, @@ -424,7 +425,7 @@ const onGoingTakeBuyMessage = async ( } }; -const beginTakeSellMessage = async (ctx: MainContext, bot: Telegraf, buyer: UserDocument, order) => { +const beginTakeSellMessage = async (ctx: MainContext, bot: Telegraf, buyer: UserDocument, order: IOrder) => { try { const holdInvoiceExpiration = holdInvoiceExpirationInSecs(); const orderExpiration = @@ -461,7 +462,7 @@ const onGoingTakeSellMessage = async ( bot: Telegraf, sellerUser: UserDocument, buyerUser: UserDocument, - order, + order: orderSchema, i18nBuyer: I18nContext, i18nSeller: I18nContext ) => { @@ -500,7 +501,7 @@ const takeSellWaitingSellerToPayMessage = async ( ctx: MainContext, bot: Telegraf, buyerUser: UserDocument, - order + order: IOrder ) => { try { await bot.telegram.sendMessage( @@ -533,7 +534,7 @@ const releasedSatsMessage = async ( } }; -const rateUserMessage = async (bot: Telegraf, caller, order, i18n: I18nContext) => { +const rateUserMessage = async (bot: Telegraf, caller, order: IOrder, i18n: I18nContext) => { try { const starButtons = []; for (let num = 5; num > 0; num--) { @@ -581,7 +582,7 @@ const notOrderMessage = async (ctx: MainContext) => { const publishBuyOrderMessage = async ( bot: Telegraf, user: UserDocument, - order, + order: IOrder, i18n: I18nContext, messageToUser: boolean ) => { @@ -615,7 +616,7 @@ const publishBuyOrderMessage = async ( const publishSellOrderMessage = async ( ctx: MainContext, user: UserDocument, - order, + order: IOrder, i18n: I18nContext, messageToUser ) => { @@ -652,7 +653,7 @@ const customMessage = async (ctx: MainContext, message: string) => { } }; -const checkOrderMessage = async (ctx: MainContext, order, buyer: UserDocument, seller: UserDocument) => { +const checkOrderMessage = async (ctx: MainContext, order: IOrder, buyer: UserDocument, seller: UserDocument) => { try { let message = getDetailedOrder(ctx.i18n, order, buyer, seller); message += `\n\n`; @@ -822,7 +823,7 @@ const notValidIdMessage = async (ctx: MainContext) => { } }; -const addInvoiceMessage = async (ctx: MainContext, bot: Telegraf, buyer: UserDocument, seller: UserDocument, order) => { +const addInvoiceMessage = async (ctx: MainContext, bot: Telegraf, buyer: UserDocument, seller: UserDocument, order: IOrder) => { try { await bot.telegram.sendMessage( buyer.tg_id, @@ -844,7 +845,7 @@ const addInvoiceMessage = async (ctx: MainContext, bot: Telegraf, } }; -const sendBuyerInfo2SellerMessage = async (bot: Telegraf, buyer: UserDocument, seller: UserDocument, order, i18n: I18nContext) => { +const sendBuyerInfo2SellerMessage = async (bot: Telegraf, buyer: UserDocument, seller: UserDocument, order: IOrder, i18n: I18nContext) => { try { await bot.telegram.sendMessage( seller.tg_id, @@ -872,7 +873,7 @@ const cantTakeOwnOrderMessage = async (ctx: MainContext, bot: Telegraf { +const notLightningInvoiceMessage = async (ctx: MainContext, order: IOrder) => { try { await ctx.reply(ctx.i18n.t('send_me_lninvoice', { amount: order.amount })); await ctx.reply( @@ -952,7 +953,7 @@ const badStatusOnCancelOrderMessage = async (ctx: MainContext) => { } }; -const successCancelOrderMessage = async (ctx: MainContext, user: UserDocument, order, i18n: I18nContext) => { +const successCancelOrderMessage = async (ctx: MainContext, user: UserDocument, order: IOrder, i18n: I18nContext) => { try { await ctx.telegram.sendMessage( user.tg_id, @@ -963,7 +964,7 @@ const successCancelOrderMessage = async (ctx: MainContext, user: UserDocument, o } }; -const counterPartyCancelOrderMessage = async (ctx: MainContext, user: UserDocument, order, i18n: I18nContext) => { +const counterPartyCancelOrderMessage = async (ctx: MainContext, user: UserDocument, order: IOrder, i18n: I18nContext) => { try { await ctx.telegram.sendMessage( user.tg_id, @@ -982,7 +983,7 @@ const successCancelAllOrdersMessage = async (ctx: MainContext) => { } }; -const successCancelOrderByAdminMessage = async (ctx: MainContext, bot: Telegraf, user: UserDocument, order) => { +const successCancelOrderByAdminMessage = async (ctx: MainContext, bot: Telegraf, user: UserDocument, order: IOrder) => { try { await bot.telegram.sendMessage( user.tg_id, @@ -993,7 +994,7 @@ const successCancelOrderByAdminMessage = async (ctx: MainContext, bot: Telegraf< } }; -const successCompleteOrderMessage = async (ctx: MainContext, order) => { +const successCompleteOrderMessage = async (ctx: MainContext, order: IOrder) => { try { await ctx.reply(ctx.i18n.t('order_completed', { orderId: order._id })); } catch (error) { @@ -1001,7 +1002,7 @@ const successCompleteOrderMessage = async (ctx: MainContext, order) => { } }; -const successCompleteOrderByAdminMessage = async (ctx: MainContext, bot: Telegraf, user: UserDocument, order) => { +const successCompleteOrderByAdminMessage = async (ctx: MainContext, bot: Telegraf, user: UserDocument, order: IOrder) => { try { await bot.telegram.sendMessage( user.tg_id, @@ -1023,7 +1024,7 @@ const shouldWaitCooperativeCancelMessage = async (ctx: MainContext, user: UserDo } }; -const okCooperativeCancelMessage = async (ctx: MainContext, user: UserDocument, order, i18n: I18nContext) => { +const okCooperativeCancelMessage = async (ctx: MainContext, user: UserDocument, order: IOrder, i18n: I18nContext) => { try { await ctx.telegram.sendMessage( user.tg_id, @@ -1045,7 +1046,7 @@ const refundCooperativeCancelMessage = async (ctx: MainContext, user: UserDocume } }; -const initCooperativeCancelMessage = async (ctx: MainContext, order) => { +const initCooperativeCancelMessage = async (ctx: MainContext, order: IOrder) => { try { await ctx.reply( ctx.i18n.t('init_cooperativecancel', { orderId: order._id }) @@ -1058,7 +1059,7 @@ const initCooperativeCancelMessage = async (ctx: MainContext, order) => { const counterPartyWantsCooperativeCancelMessage = async ( ctx: MainContext, user: UserDocument, - order, + order: IOrder, i18n: I18nContext ) => { try { @@ -1207,7 +1208,7 @@ const tooManyPendingOrdersMessage = async (ctx: MainContext, user: UserDocument, const wizardAddInvoiceInitMessage = async ( ctx: MainContext, - order, + order: IOrder, currency: string, expirationTime: number ) => { @@ -1225,7 +1226,7 @@ const wizardAddInvoiceInitMessage = async ( } }; -const wizardAddInvoiceExitMessage = async (ctx: MainContext, order) => { +const wizardAddInvoiceExitMessage = async (ctx: MainContext, order: IOrder) => { try { await ctx.reply( ctx.i18n.t('wizard_add_invoice_exit', { @@ -1271,7 +1272,7 @@ const sendMeAnInvoiceMessage = async (ctx: MainContext, amount: number, i18nCtx } }; -const wizardAddFiatAmountMessage = async (ctx: MainContext, currency: string, action, order) => { +const wizardAddFiatAmountMessage = async (ctx: MainContext, currency: string, action, order: IOrder) => { try { await ctx.reply( ctx.i18n.t('wizard_add_fiat_amount', { @@ -1287,7 +1288,7 @@ const wizardAddFiatAmountMessage = async (ctx: MainContext, currency: string, a } }; -const wizardAddFiatAmountWrongAmountMessage = async (ctx: MainContext, order) => { +const wizardAddFiatAmountWrongAmountMessage = async (ctx: MainContext, order: IOrder) => { try { ctx.deleteMessage(); await ctx.reply( @@ -1314,7 +1315,7 @@ const wizardAddFiatAmountCorrectMessage = async (ctx: MainContext, currency, fia } }; -const expiredOrderMessage = async (bot: Telegraf, order, buyerUser: UserDocument, sellerUser: UserDocument, i18n: I18nContext) => { +const expiredOrderMessage = async (bot: Telegraf, order: IOrder, buyerUser: UserDocument, sellerUser: UserDocument, i18n: I18nContext) => { try { const detailedOrder = getDetailedOrder(i18n, order, buyerUser, sellerUser); await bot.telegram.sendMessage( @@ -1353,7 +1354,7 @@ const toSellerExpiredOrderMessage = async (bot: Telegraf, user: Use } }; -const toBuyerDidntAddInvoiceMessage = async (bot: Telegraf, user: UserDocument, order, i18n: I18nContext) => { +const toBuyerDidntAddInvoiceMessage = async (bot: Telegraf, user: UserDocument, order: IOrder, i18n: I18nContext) => { try { await bot.telegram.sendMessage( user.tg_id, @@ -1364,7 +1365,7 @@ const toBuyerDidntAddInvoiceMessage = async (bot: Telegraf, user: U } }; -const toSellerBuyerDidntAddInvoiceMessage = async (bot: Telegraf, user: UserDocument, order, i18n: I18nContext) => { +const toSellerBuyerDidntAddInvoiceMessage = async (bot: Telegraf, user: UserDocument, order: IOrder, i18n: I18nContext) => { try { await bot.telegram.sendMessage( user.tg_id, @@ -1378,7 +1379,7 @@ const toSellerBuyerDidntAddInvoiceMessage = async (bot: Telegraf, u const toAdminChannelBuyerDidntAddInvoiceMessage = async ( bot: Telegraf, user: UserDocument, - order, + order: IOrder, i18n: I18nContext ) => { try { @@ -1394,7 +1395,7 @@ const toAdminChannelBuyerDidntAddInvoiceMessage = async ( } }; -const toSellerDidntPayInvoiceMessage = async (bot: Telegraf, user: UserDocument, order, i18n: I18nContext) => { +const toSellerDidntPayInvoiceMessage = async (bot: Telegraf, user: UserDocument, order: IOrder, i18n: I18nContext) => { try { await bot.telegram.sendMessage( user.tg_id, @@ -1405,7 +1406,7 @@ const toSellerDidntPayInvoiceMessage = async (bot: Telegraf, user: } }; -const toBuyerSellerDidntPayInvoiceMessage = async (bot: Telegraf, user: UserDocument, order, i18n: I18nContext) => { +const toBuyerSellerDidntPayInvoiceMessage = async (bot: Telegraf, user: UserDocument, order: IOrder, i18n: I18nContext) => { try { await bot.telegram.sendMessage( user.tg_id, @@ -1419,7 +1420,7 @@ const toBuyerSellerDidntPayInvoiceMessage = async (bot: Telegraf, u const toAdminChannelSellerDidntPayInvoiceMessage = async ( bot: Telegraf, user: UserDocument, - order, + order: IOrder, i18n: I18nContext ) => { try { @@ -1438,7 +1439,7 @@ const toAdminChannelSellerDidntPayInvoiceMessage = async ( const toAdminChannelPendingPaymentSuccessMessage = async ( bot: Telegraf, user: UserDocument, - order, + order: IOrder, pending, payment, i18n: I18nContext @@ -1462,7 +1463,7 @@ const toAdminChannelPendingPaymentSuccessMessage = async ( const toBuyerPendingPaymentSuccessMessage = async ( bot: Telegraf, user: UserDocument, - order, + order: IOrder, payment, i18n: I18nContext ) => { @@ -1480,7 +1481,7 @@ const toBuyerPendingPaymentSuccessMessage = async ( } }; -const toBuyerPendingPaymentFailedMessage = async (bot: Telegraf, user: UserDocument, order, i18n: I18nContext) => { +const toBuyerPendingPaymentFailedMessage = async (bot: Telegraf, user: UserDocument, order: IOrder, i18n: I18nContext) => { try { const attempts = process.env.PAYMENT_ATTEMPTS; await bot.telegram.sendMessage( @@ -1509,7 +1510,7 @@ const toBuyerPendingPaymentFailedMessage = async (bot: Telegraf, us const toAdminChannelPendingPaymentFailedMessage = async ( bot: Telegraf, user: UserDocument, - order, + order: IOrder, pending, i18n: I18nContext ) => { diff --git a/models/order.js b/models/order.js deleted file mode 100644 index 77519d8f..00000000 --- a/models/order.js +++ /dev/null @@ -1,85 +0,0 @@ -const mongoose = require('mongoose'); - -const OrderSchema = new mongoose.Schema({ - description: { type: String, required: true }, - amount: { - // amount in satoshis - type: Number, - min: 0, - }, - max_amount: { - // max amount in fiat - type: Number, - min: 0, - }, - min_amount: { - // min amount in fiat - type: Number, - min: 0, - }, - fee: { type: Number, min: 0 }, - bot_fee: { type: Number, min: 0 }, // bot MAX_FEE at the moment of order creation - community_fee: { type: Number, min: 0 }, // community FEE_PERCENT at the moment of order creation - routing_fee: { type: Number, min: 0, default: 0 }, - hash: { - type: String, - index: { - unique: true, - partialFilterExpression: { hash: { $type: 'string' } }, - }, - }, // hold invoice hash - secret: { - type: String, - index: { - unique: true, - partialFilterExpression: { secret: { $type: 'string' } }, - }, - }, // hold invoice secret - creator_id: { type: String }, - seller_id: { type: String }, - buyer_id: { type: String }, - buyer_invoice: { type: String }, - buyer_dispute: { type: Boolean, default: false }, - seller_dispute: { type: Boolean, default: false }, - buyer_cooperativecancel: { type: Boolean, default: false }, - seller_cooperativecancel: { type: Boolean, default: false }, - canceled_by: { type: String }, - status: { - type: String, - enum: [ - 'WAITING_PAYMENT', // buyer waiting for seller pay hold invoice - 'WAITING_BUYER_INVOICE', // seller waiting for buyer add invoice where will receive sats - 'PENDING', // order published on CHANNEL but not taken yet - 'ACTIVE', // order taken - 'FIAT_SENT', // buyer indicates the fiat payment is already done - 'CLOSED', // order closed - 'DISPUTE', // one of the parties started a dispute - 'CANCELED', - 'SUCCESS', - 'PAID_HOLD_INVOICE', // seller released funds - 'CANCELED_BY_ADMIN', - 'EXPIRED', // Expired orders, stated changed by a job - 'COMPLETED_BY_ADMIN', - ], - }, - type: { type: String }, - fiat_amount: { type: Number, min: 1 }, // amount in fiat - fiat_code: { type: String }, - payment_method: { type: String, required: true }, - created_at: { type: Date, default: Date.now }, - invoice_held_at: { type: Date }, - taken_at: { type: Date }, - tg_chat_id: { type: String }, - tg_order_message: { type: String }, - tg_channel_message1: { type: String }, - range_parent_id: { type: String }, // If the order have a parent we save the Id - price_from_api: { type: Boolean }, - price_margin: { type: Number, default: 0 }, - calculated: { type: Boolean, default: false }, - admin_warned: { type: Boolean, default: false }, // We set this to true when the bot warns admins the order is about to expire - paid_hold_buyer_invoice_updated: { type: Boolean, default: false }, // We set this to true when buyer executes /setinvoice on a order PAID_HOLD_INVOICE - community_id: { type: String }, - is_public: { type: Boolean, default: true }, -}); - -module.exports = mongoose.model('Order', OrderSchema); diff --git a/models/order.ts b/models/order.ts new file mode 100644 index 00000000..a17c630a --- /dev/null +++ b/models/order.ts @@ -0,0 +1,126 @@ +import mongoose, { Document, Schema } from 'mongoose'; + +export interface IOrder extends Document { + description?: string; + amount: number; + max_amount: number; + min_amount: number; + fee: number; + bot_fee: number; + community_fee:number; + routing_fee: number; + hash: string; + secret: string; + creator_id: string; + seller_id: string; + buyer_id: string; + buyer_invoice: string; + buyer_dispute: boolean + seller_dispute: boolean + buyer_cooperativecancel: boolean; + seller_cooperativecancel: boolean; + canceled_by: string + status: string; + type: string; + fiat_amount: number; + fiat_code: string; + payment_method: string; + created_at: Date; + invoice_held_at: Date; + taken_at: Date; + tg_chat_id: string; + tg_order_message: string; + tg_channel_message1: string; + range_parent_id: string; + price_from_api: boolean; + price_margin: number; + calculated: boolean; + admin_warned: boolean; + paid_hold_buyer_invoice_updated: boolean; + community_id: string; + is_public: boolean; +} + +const orderSchema = new Schema({ + description: { type: String, required: true }, + amount: { + // amount in satoshis + type: Number, + min: 0, + }, + max_amount: { + // max amount in fiat + type: Number, + min: 0, + }, + min_amount: { + // min amount in fiat + type: Number, + min: 0, + }, + fee: { type: Number, min: 0 }, + bot_fee: { type: Number, min: 0 }, // bot MAX_FEE at the moment of order creation + community_fee: { type: Number, min: 0 }, // community FEE_PERCENT at the moment of order creation + routing_fee: { type: Number, min: 0, default: 0 }, + hash: { + type: String, + index: { + unique: true, + partialFilterExpression: { hash: { $type: 'string' } }, + }, + }, // hold invoice hash + secret: { + type: String, + index: { + unique: true, + partialFilterExpression: { secret: { $type: 'string' } }, + }, + }, // hold invoice secret + creator_id: { type: String }, + seller_id: { type: String }, + buyer_id: { type: String }, + buyer_invoice: { type: String }, + buyer_dispute: { type: Boolean, default: false }, + seller_dispute: { type: Boolean, default: false }, + buyer_cooperativecancel: { type: Boolean, default: false }, + seller_cooperativecancel: { type: Boolean, default: false }, + canceled_by: { type: String }, + status: { + type: String, + enum: [ + 'WAITING_PAYMENT', // buyer waiting for seller pay hold invoice + 'WAITING_BUYER_INVOICE', // seller waiting for buyer add invoice where will receive sats + 'PENDING', // order published on CHANNEL but not taken yet + 'ACTIVE', // order taken + 'FIAT_SENT', // buyer indicates the fiat payment is already done + 'CLOSED', // order closed + 'DISPUTE', // one of the parties started a dispute + 'CANCELED', + 'SUCCESS', + 'PAID_HOLD_INVOICE', // seller released funds + 'CANCELED_BY_ADMIN', + 'EXPIRED', // Expired orders, stated changed by a job + 'COMPLETED_BY_ADMIN', + ], + }, + type: { type: String }, + fiat_amount: { type: Number, min: 1 }, // amount in fiat + fiat_code: { type: String }, + payment_method: { type: String, required: true }, + created_at: { type: Date, default: Date.now }, + invoice_held_at: { type: Date }, + taken_at: { type: Date }, + tg_chat_id: { type: String }, + tg_order_message: { type: String }, + tg_channel_message1: { type: String }, + range_parent_id: { type: String }, // If the order have a parent we save the Id + price_from_api: { type: Boolean }, + price_margin: { type: Number, default: 0 }, + calculated: { type: Boolean, default: false }, + admin_warned: { type: Boolean, default: false }, // We set this to true when the bot warns admins the order is about to expire + paid_hold_buyer_invoice_updated: { type: Boolean, default: false }, // We set this to true when buyer executes /setinvoice on a order PAID_HOLD_INVOICE + community_id: { type: String }, + is_public: { type: Boolean, default: true } +}); + +module.exports = mongoose.model('Order', orderSchema);