Skip to content

Commit

Permalink
new feature: Freeze orders
Browse files Browse the repository at this point in the history
This can be used on very weird cases where buyer
use a really slow system to send money and to protect
both parties we must freeze the order
  • Loading branch information
grunch committed Dec 18, 2023
1 parent 737b197 commit f8f64a6
Show file tree
Hide file tree
Showing 12 changed files with 120 additions and 58 deletions.
35 changes: 35 additions & 0 deletions bot/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,41 @@ const initialize = (botToken: string, options: Partial<Telegraf.Options<MainCont

DisputeModule.configure(bot);

bot.command('freezeorder', adminMiddleware, async (ctx: MainContext) => {
try {
const [orderId] = await validateParams(ctx, 2, '\\<_order id_\\>');

if (!orderId) return;
if (!(await validateObjectId(ctx, orderId))) return;

const order = await Order.findOne({ _id: orderId });

if (!order) return;

// We check if this is a solver, the order must be from the same community
if (!ctx.admin.admin) {
if (!order.community_id) {
return await messages.notAuthorized(ctx);
}

if (order.community_id != ctx.admin.default_community_id) {
return await messages.notAuthorized(ctx);
}
}

order.is_frozen = true;
order.status = 'FROZEN';
order.action_by = ctx.admin._id;
await order.save();

if (order.secret) await settleHoldInvoice({ secret: order.secret });

await ctx.reply(ctx.i18n.t('order_frozen'));
} catch (error) {
logger.error(error);
}
});

bot.command('cancelorder', adminMiddleware, async (ctx: MainContext) => {
try {
const [orderId] = await validateParams(ctx, 2, '\\<_order id_\\>');
Expand Down
3 changes: 2 additions & 1 deletion ln/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const {
cancelHoldInvoice,
getInvoice,
} = require('./hold_invoice');
const subscribeInvoice = require('./subscribe_invoice');
const { subscribeInvoice, payHoldInvoice } = require('./subscribe_invoice');
const subscribeProbe = require('./subscribe_probe');
const resubscribeInvoices = require('./resubscribe_invoices');
const { payRequest, payToBuyer, isPendingPayment } = require('./pay_request');
Expand All @@ -22,4 +22,5 @@ module.exports = {
isPendingPayment,
subscribeProbe,
getInvoice,
payHoldInvoice,
};
126 changes: 70 additions & 56 deletions ln/subscribe_invoice.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,70 +55,84 @@ const subscribeInvoice = async (bot, id, resub) => {
logger.info(
`Order ${order._id} - Invoice with hash: ${id} was settled!`
);
order.status = 'PAID_HOLD_INVOICE';
await order.save();
const buyerUser = await User.findOne({ _id: order.buyer_id });
const sellerUser = await User.findOne({ _id: order.seller_id });
// We need two i18n contexts to send messages to each user
const i18nCtxBuyer = await getUserI18nContext(buyerUser);
const i18nCtxSeller = await getUserI18nContext(sellerUser);
await messages.releasedSatsMessage(
bot,
sellerUser,
buyerUser,
i18nCtxBuyer,
i18nCtxSeller
);
// If this is a range order, probably we need to created a new child range order
const orderData = await ordersActions.getNewRangeOrderPayload(order);
let i18nCtx;
if (orderData) {
let user;
if (order.type === 'sell') {
user = sellerUser;
i18nCtx = i18nCtxSeller;
} else {
user = buyerUser;
i18nCtx = i18nCtxBuyer;
}
if (order.status === 'FROZEN' && order.is_frozen) {
logger.info(
`Order ${order._id} - Order was frozen by ${order.action_by}!`
);
return;
}
await payHoldInvoice(bot, order);
}
});
} catch (error) {
logger.error('subscribeInvoice catch: ', error);
return false;
}
};

const newOrder = await ordersActions.createOrder(
const payHoldInvoice = async (bot, order) => {
try {
order.status = 'PAID_HOLD_INVOICE';
await order.save();
const buyerUser = await User.findOne({ _id: order.buyer_id });
const sellerUser = await User.findOne({ _id: order.seller_id });
// We need two i18n contexts to send messages to each user
const i18nCtxBuyer = await getUserI18nContext(buyerUser);
const i18nCtxSeller = await getUserI18nContext(sellerUser);
await messages.releasedSatsMessage(
bot,
sellerUser,
buyerUser,
i18nCtxBuyer,
i18nCtxSeller
);
// If this is a range order, probably we need to created a new child range order
const orderData = await ordersActions.getNewRangeOrderPayload(order);
let i18nCtx;
if (orderData) {
let user;
if (order.type === 'sell') {
user = sellerUser;
i18nCtx = i18nCtxSeller;
} else {
user = buyerUser;
i18nCtx = i18nCtxBuyer;
}

const newOrder = await ordersActions.createOrder(
i18nCtx,
bot,
user,
orderData
);

if (newOrder) {
if (order.type === 'sell') {
await messages.publishSellOrderMessage(
bot,
user,
newOrder,
i18nCtx,
true
);
} else {
await messages.publishBuyOrderMessage(
bot,
user,
orderData
newOrder,
i18nCtx,
true
);

if (newOrder) {
if (order.type === 'sell') {
await messages.publishSellOrderMessage(
bot,
user,
newOrder,
i18nCtx,
true
);
} else {
await messages.publishBuyOrderMessage(
bot,
user,
newOrder,
i18nCtx,
true
);
}
}
}
// The seller get reputation after release
await messages.rateUserMessage(bot, sellerUser, order, i18nCtxSeller);
// We proceed to pay to buyer
await payToBuyer(bot, order);
}
});
}
// The seller get reputation after release
await messages.rateUserMessage(bot, sellerUser, order, i18nCtxSeller);
// We proceed to pay to buyer
await payToBuyer(bot, order);
} catch (error) {
logger.error('subscribeInvoice catch: ', error);
return false;
logger.error('payHoldInvoice catch: ', error);
}
};

module.exports = subscribeInvoice;
module.exports = { subscribeInvoice, payHoldInvoice };
1 change: 1 addition & 0 deletions locales/de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -583,3 +583,4 @@ disclaimer: |
Die Entwickler und die Streitschlichter bemühen sich nach besten Kräften, die Nutzung des Bots durch böswillige Akteure, Betrüger und Schwindler zu unterbinden, aber der Nutzer erkennt an, dass das System ausgenutzt werden kann, und übernimmt die volle Verantwortung für seine Nutzung.
Weder die Entwickler noch die Streitschlichter sind für Verluste oder Schäden verantwortlich, die dem Benutzer durch die Nutzung des Bots entstehen können.
order_frozen: Sie haben die Bestellung eingefroren
2 changes: 1 addition & 1 deletion locales/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -583,4 +583,4 @@ disclaimer: |
The developers and the dispute resolvers make their best efforts to remove bad actors, frauds, and scams from using the bot, but the user recognizes that the system can be exploited and accepts full responsibility while using it.
Neither the developers nor the dispute resolvers are responsible for any losses or damages that the user may suffer as a result of using the bot.
order_frozen: You have frozen the order
1 change: 1 addition & 0 deletions locales/es.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -585,3 +585,4 @@ disclaimer: |
Los desarrolladores y los árbitros de disputas hacen todo lo posible para eliminar a los actores malintencionados y estafadores del uso del bot, pero el usuario reconoce que el sistema puede ser atacado y acepta la plena responsabilidad al ejecutarlo.
Ni los desarrolladores ni los árbitros de disputas son responsables de las pérdidas o daños que el usuario pueda sufrir como resultado del uso del bot.
order_frozen: Has congelado la orden
1 change: 1 addition & 0 deletions locales/fr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -583,3 +583,4 @@ disclaimer: |
Les développeurs et les responsables de la résolution des litiges font de leur mieux pour empêcher les mauvais acteurs, les fraudes et les escroqueries d'utiliser le bot, mais l'utilisateur reconnaît que le système peut être exploité et en accepte l'entière responsabilité lorsqu'il l'utilise.
Ni les développeurs ni les responsables de la résolution des litiges ne sont responsables des pertes ou des dommages que l'utilisateur pourrait subir à la suite de l'utilisation du bot.
order_frozen : Vous avez gelé la commande
1 change: 1 addition & 0 deletions locales/it.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -580,3 +580,4 @@ disclaimer: |
Gli sviluppatori e i risolutori di controversie fanno del loro meglio per eliminare i cattivi attori, le frodi e le truffe dall'uso del bot, ma l'utente riconosce che il sistema può essere sfruttato e si assume la piena responsabilità del suo utilizzo.
Né gli sviluppatori né i risolutori di controversie sono responsabili di eventuali perdite o danni che l'utente potrebbe subire a causa dell'utilizzo del bot.
order_frozen: hai congelato l'ordine
1 change: 1 addition & 0 deletions locales/pt.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -580,3 +580,4 @@ disclaimer: |
Os criadores e os responsáveis pela resolução de litígios envidam os seus melhores esforços para impedir que os maus actores, as fraudes e as burlas utilizem o bot, mas o utilizador reconhece que o sistema pode ser explorado e aceita toda a responsabilidade enquanto o utiliza.
Nem os criadores nem os solucionadores de litígios são responsáveis por quaisquer perdas ou danos que o utilizador possa sofrer como resultado da utilização do bot.
order_frozen: Você congelou o pedido
1 change: 1 addition & 0 deletions locales/ru.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -582,3 +582,4 @@ disclaimer: |
Разработчики и специалисты по разрешению споров прилагают все усилия, чтобы исключить использование бота недобросовестными участниками, мошенниками и аферистами, однако пользователь осознает, что система может быть использована, и принимает на себя всю ответственность при ее использовании.
Ни разработчики, ни разрешители споров не несут ответственности за какие-либо потери или убытки, которые могут возникнуть у пользователя в результате использования бота.
order_frozen: вы заморозили заказ
1 change: 1 addition & 0 deletions locales/uk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -579,3 +579,4 @@ disclaimer: |
Розробники та особи, які вирішують суперечки, докладають усіх зусиль, щоб усунути недобросовісних учасників, шахраїв та аферистів від використання бота, але користувач визнає, що система може бути використана, і бере на себе повну відповідальність при її використанні.
Ані розробники, ані сторони, що вирішують спори, не несуть відповідальності за будь-які збитки або шкоду, яких користувач може зазнати в результаті використання бота.
order_frozen: Ви заморозили замовлення
5 changes: 5 additions & 0 deletions models/order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface IOrder extends Document {
buyer_cooperativecancel: boolean;
seller_cooperativecancel: boolean;
canceled_by: string
action_by: string
status: string;
type: string;
fiat_amount: number;
Expand All @@ -38,6 +39,7 @@ export interface IOrder extends Document {
admin_warned: boolean;
paid_hold_buyer_invoice_updated: boolean;
community_id: string;
is_frozen: boolean;
is_public: boolean;
}

Expand Down Expand Up @@ -85,6 +87,7 @@ const orderSchema = new Schema<IOrder>({
buyer_cooperativecancel: { type: Boolean, default: false },
seller_cooperativecancel: { type: Boolean, default: false },
canceled_by: { type: String },
action_by: { type: String },
status: {
type: String,
enum: [
Expand All @@ -101,6 +104,7 @@ const orderSchema = new Schema<IOrder>({
'CANCELED_BY_ADMIN',
'EXPIRED', // Expired orders, stated changed by a job
'COMPLETED_BY_ADMIN',
'FROZEN',
],
},
type: { type: String },
Expand All @@ -121,6 +125,7 @@ const orderSchema = new Schema<IOrder>({
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 },
is_frozen: { type: Boolean, default: false },
});

module.exports = mongoose.model<IOrder>('Order', orderSchema);

0 comments on commit f8f64a6

Please sign in to comment.