Skip to content

Commit d3efdc0

Browse files
authored
Merge pull request #3503 from hollaex/develop
Develop
2 parents 334bcd2 + 068d6d8 commit d3efdc0

File tree

6 files changed

+1302
-1180
lines changed

6 files changed

+1302
-1180
lines changed

server/mail/templates/index.js

Lines changed: 100 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,12 @@ const replaceHTMLContent = (type, html = '', email, data, language, domain) => {
133133
if (EXPLORERS[data.currency]) {
134134
EXPLORERS[data.currency].forEach((explorer) => {
135135
explorers += `<li><a href=${explorer.baseUrl}${explorer.txPath}/${data.transaction_id
136-
}>${explorer.name}</a></li>`;
136+
}>${explorer.name}</a></li>`;
137137
});
138138
} else if (EXPLORERS[data.network]) {
139139
EXPLORERS[data.network].forEach((explorer) => {
140140
explorers += `<li><a href=${explorer.baseUrl}${explorer.txPath}/${data.transaction_id
141-
}>${explorer.name}</a></li>`;
141+
}>${explorer.name}</a></li>`;
142142
});
143143
}
144144
}
@@ -150,16 +150,33 @@ const replaceHTMLContent = (type, html = '', email, data, language, domain) => {
150150
html = html.replace(/\$\{amount\}/g, data.amount || '');
151151
html = html.replace(/\$\{confirmation\}/g, confirmation || '');
152152
html = html.replace(/\$\{status\}/g, data.status || '');
153-
html = html.replace(/\$\{address\}/g, data.address || '');
153+
if (data.address) {
154+
html = html.replace(/\$\{address\}/g, data.address || '');
155+
} else {
156+
html = html.replace(
157+
/<div id='address'[^>]*>[\s\S]*?<\/div>/,
158+
'' // skip
159+
);
160+
}
154161
html = html.replace(/\$\{transaction_id\}/g, data.transaction_id || '');
155162
html = html.replace(/\$\{fee\}/g, data.fee || '0');
156163
html = html.replace(/\$\{description\}/g, data.description || '');
157-
html = html.replace(/\$\{explorers\}/g, explorers || '');
164+
if (explorers && explorers.length > 0) {
165+
html = html.replace(/\$\{explorers\}/g, explorers || '');
166+
} else {
167+
html = html.replace(
168+
/<div id='explorers'[^>]*>[\s\S]*?<\/div>/,
169+
'' // skip
170+
);
171+
}
158172
html = html.replace(/\$\{api_name\}/g, API_NAME() || '');
159173
if (data.network) {
160174
html = html.replace(/\$\{network\}/g, data.network || '');
161175
} else {
162-
html = html.replace(/id="network"/g, 'style="display: none"');
176+
html = html.replace(
177+
/<div id='network'[^>]*>[\s\S]*?<\/div>/,
178+
'' // skip
179+
);
163180
}
164181

165182
}
@@ -173,12 +190,12 @@ const replaceHTMLContent = (type, html = '', email, data, language, domain) => {
173190
if (EXPLORERS[data.currency]) {
174191
EXPLORERS[data.currency].forEach((explorer) => {
175192
explorers += `<li><a href=${explorer.baseUrl}${explorer.txPath}/${data.transaction_id
176-
}>${explorer.name}</a></li>`;
193+
}>${explorer.name}</a></li>`;
177194
});
178195
} else if (EXPLORERS[data.network]) {
179196
EXPLORERS[data.network].forEach((explorer) => {
180197
explorers += `<li><a href=${explorer.baseUrl}${explorer.txPath}/${data.transaction_id
181-
}>${explorer.name}</a></li>`;
198+
}>${explorer.name}</a></li>`;
182199
});
183200
}
184201
}
@@ -191,18 +208,34 @@ const replaceHTMLContent = (type, html = '', email, data, language, domain) => {
191208
html = html.replace(/\$\{amount\}/g, data.amount || ''); //
192209
html = html.replace(/\$\{confirmation\}/g, confirmation || '');
193210
html = html.replace(/\$\{status\}/g, data.status || '');
194-
html = html.replace(/\$\{address\}/g, data.address || '');
211+
if (data.address) {
212+
html = html.replace(/\$\{address\}/g, data.address || '');
213+
} else {
214+
html = html.replace(
215+
/<div id='address'[^>]*>[\s\S]*?<\/div>/,
216+
'' // skip
217+
);
218+
}
195219
html = html.replace(/\$\{transaction_id\}/g, data.transaction_id || '');
196220
html = html.replace(/\$\{fee\}/g, data.fee || '0');
197221
html = html.replace(/\$\{description\}/g, data.description || '');
198-
html = html.replace(/\$\{explorers\}/g, explorers || '');
222+
if (explorers && explorers.length > 0) {
223+
html = html.replace(/\$\{explorers\}/g, explorers || '');
224+
} else {
225+
html = html.replace(
226+
/<div id='explorers'[^>]*>[\s\S]*?<\/div>/,
227+
'' // skip
228+
);
229+
}
199230
html = html.replace(/\$\{api_name\}/g, API_NAME() || '');
200231
if (data.network) {
201232
html = html.replace(/\$\{network\}/g, data.network || '');
202233
} else {
203-
html = html.replace(/id="network"/g, 'style="display: none"');
234+
html = html.replace(
235+
/<div id='network'[^>]*>[\s\S]*?<\/div>/,
236+
'' // skip
237+
);
204238
}
205-
206239
}
207240
else if (type === MAILTYPE.WITHDRAWAL_PENDING) {
208241

@@ -212,12 +245,12 @@ const replaceHTMLContent = (type, html = '', email, data, language, domain) => {
212245
if (EXPLORERS[data.currency]) {
213246
EXPLORERS[data.currency].forEach((explorer) => {
214247
explorers += `<li><a href=${explorer.baseUrl}${explorer.txPath}/${data.transaction_id
215-
}>${explorer.name}</a></li>`;
248+
}>${explorer.name}</a></li>`;
216249
});
217250
} else if (EXPLORERS[data.network]) {
218251
EXPLORERS[data.network].forEach((explorer) => {
219252
explorers += `<li><a href=${explorer.baseUrl}${explorer.txPath}/${data.transaction_id
220-
}>${explorer.name}</a></li>`;
253+
}>${explorer.name}</a></li>`;
221254
});
222255
}
223256
}
@@ -232,14 +265,31 @@ const replaceHTMLContent = (type, html = '', email, data, language, domain) => {
232265
html = html.replace(/\$\{amount\}/g, data.amount || '');
233266
html = html.replace(/\$\{fee\}/g, data.fee || '0');
234267
html = html.replace(/\$\{status\}/g, data.status || '');
235-
html = html.replace(/\$\{address\}/g, data.address || '');
268+
if (data.address) {
269+
html = html.replace(/\$\{address\}/g, data.address || '');
270+
} else {
271+
html = html.replace(
272+
/<div id='address'[^>]*>[\s\S]*?<\/div>/,
273+
'' // skip
274+
);
275+
}
236276
html = html.replace(/\$\{description\}/g, data.description || '');
237-
html = html.replace(/\$\{explorers\}/g, explorers || '');
277+
if (explorers && explorers.length > 0) {
278+
html = html.replace(/\$\{explorers\}/g, explorers || '');
279+
} else {
280+
html = html.replace(
281+
/<div id='explorers'[^>]*>[\s\S]*?<\/div>/,
282+
'' // skip
283+
);
284+
}
238285
html = html.replace(/\$\{transaction_id\}/g, data.transaction_id || '');
239286
if (data.network) {
240287
html = html.replace(/\$\{network\}/g, data.network || '');
241288
} else {
242-
html = html.replace(/id="network"/g, 'style="display: none"');
289+
html = html.replace(
290+
/<div id='network'[^>]*>[\s\S]*?<\/div>/,
291+
'' // skip
292+
);
243293
}
244294
}
245295
else if (type === MAILTYPE.WITHDRAWAL_COMPLETED) {
@@ -250,12 +300,12 @@ const replaceHTMLContent = (type, html = '', email, data, language, domain) => {
250300
if (EXPLORERS[data.currency]) {
251301
EXPLORERS[data.currency].forEach((explorer) => {
252302
explorers += `<li><a href=${explorer.baseUrl}${explorer.txPath}/${data.transaction_id
253-
}>${explorer.name}</a></li>`;
303+
}>${explorer.name}</a></li>`;
254304
});
255305
} else if (EXPLORERS[data.network]) {
256306
EXPLORERS[data.network].forEach((explorer) => {
257307
explorers += `<li><a href=${explorer.baseUrl}${explorer.txPath}/${data.transaction_id
258-
}>${explorer.name}</a></li>`;
308+
}>${explorer.name}</a></li>`;
259309
});
260310
}
261311
}
@@ -269,14 +319,31 @@ const replaceHTMLContent = (type, html = '', email, data, language, domain) => {
269319
html = html.replace(/\$\{amount\}/g, data.amount || '');
270320
html = html.replace(/\$\{fee\}/g, data.fee || '0');
271321
html = html.replace(/\$\{status\}/g, data.status || '');
272-
html = html.replace(/\$\{address\}/g, data.address || '');
322+
if (data.address) {
323+
html = html.replace(/\$\{address\}/g, data.address || '');
324+
} else {
325+
html = html.replace(
326+
/<div id='address'[^>]*>[\s\S]*?<\/div>/,
327+
'' // skip
328+
);
329+
}
273330
html = html.replace(/\$\{description\}/g, data.description || '');
274-
html = html.replace(/\$\{explorers\}/g, explorers || '');
331+
if (explorers && explorers.length > 0) {
332+
html = html.replace(/\$\{explorers\}/g, explorers || '');
333+
} else {
334+
html = html.replace(
335+
/<div id='explorers'[^>]*>[\s\S]*?<\/div>/,
336+
'' // skip
337+
);
338+
}
275339
html = html.replace(/\$\{transaction_id\}/g, data.transaction_id || '');
276340
if (data.network) {
277341
html = html.replace(/\$\{network\}/g, data.network || '');
278342
} else {
279-
html = html.replace(/id="network"/g, 'style="display: none"');
343+
html = html.replace(
344+
/<div id='network'[^>]*>[\s\S]*?<\/div>/,
345+
'' // skip
346+
);
280347
}
281348
}
282349
else if (type === MAILTYPE.ACCOUNT_VERIFY) { //ok
@@ -320,13 +387,23 @@ const replaceHTMLContent = (type, html = '', email, data, language, domain) => {
320387
html = html.replace(/\$\{api_name\}/g, API_NAME() || '');
321388
html = html.replace(/\$\{amount\}/g, data.amount || '');
322389
html = html.replace(/\$\{fee\}/g, data.fee || '0');
323-
html = html.replace(/\$\{address\}/g, data.address || '');
390+
if (data.address) {
391+
html = html.replace(/\$\{address\}/g, data.address || '');
392+
} else {
393+
html = html.replace(
394+
/<div id='address'[^>]*>[\s\S]*?<\/div>/,
395+
'' // skip
396+
);
397+
}
324398
html = html.replace(/\$\{ip\}/g, data.ip || '');
325399
html = html.replace(/\$\{link\}/g, data.confirmation_link || `${domain}/confirm-withdraw/${data.transaction_id}?currency=${data.currency}&amount=${data.amount}&address=${data.address}&fee=${data.fee}&fee_coin=${data.fee_coin}&network=${data.network}`);
326400
if (data.network) {
327401
html = html.replace(/\$\{network\}/g, data.network || '');
328402
} else {
329-
html = html.replace(/id="network"/g, 'style="display: none"');
403+
html = html.replace(
404+
/<div id='network'[^>]*>[\s\S]*?<\/div>/,
405+
'' // skip
406+
);
330407
}
331408
}
332409
else if (type === MAILTYPE.INVALID_ADDRESS) {

server/plugins/job.js

Lines changed: 62 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -318,23 +318,22 @@ const scheduleAutoTrade = () => {
318318
const timezone = getTimezone();
319319
const now = moment().tz(timezone);
320320
const currentHour = now.hour();
321-
const currentDay = now.day();
322-
const currentDate = now.date();
323-
const lastExecutionThreshold = now.clone().subtract(1, 'day').startOf('day');
321+
const today = now.clone().startOf('day');
322+
323+
const hoursToCheck = [
324+
currentHour,
325+
(currentHour - 1 + 24) % 24,
326+
(currentHour - 2 + 24) % 24,
327+
];
324328

325329
const autoTradeConfigs = await autoTradeConfigModel.findAll({
326330
where: {
327331
active: true,
328-
trade_hour: currentHour,
329-
[Op.or]: [
330-
{ last_execution_date: { [Op.is]: null } },
331-
{ last_execution_date: { [Op.lt]: lastExecutionThreshold.toDate() } },
332-
{ frequency: 'daily' }
333-
],
332+
trade_hour: hoursToCheck,
334333
[Op.or]: [
335334
{ frequency: 'daily' },
336-
{ frequency: 'weekly', week_days: { [Op.contains]: [currentDay] } },
337-
{ frequency: 'monthly', day_of_month: currentDate }
335+
{ frequency: 'weekly' },
336+
{ frequency: 'monthly' }
338337
]
339338
}
340339
});
@@ -345,17 +344,62 @@ const scheduleAutoTrade = () => {
345344
}
346345

347346
for (const autoTradeConfig of autoTradeConfigs) {
348-
const { trade_hour, user_id, spend_coin, buy_coin, spend_amount, last_execution_date } = autoTradeConfig;
347+
const {
348+
frequency,
349+
week_days,
350+
day_of_month,
351+
last_execution_date,
352+
trade_hour,
353+
user_id,
354+
spend_coin,
355+
buy_coin,
356+
spend_amount,
357+
} = autoTradeConfig;
349358

350-
let lastExecDate = last_execution_date ? moment(last_execution_date).tz(timezone) : now.clone().subtract(1, 'day');
359+
const lastExecDate = last_execution_date
360+
? moment(last_execution_date).tz(timezone)
361+
: null;
351362

352-
while (lastExecDate.isBefore(now, 'day')) {
353-
lastExecDate.add(1, 'day');
354-
loggerPlugin.verbose('plugins/job/scheduleAutoTrade auto trade job config', autoTradeConfig);
363+
let shouldRun = false;
355364

356-
await executeTrade(autoTradeConfig);
365+
if (!lastExecDate || lastExecDate.isBefore(today, 'day')) {
366+
if (frequency === 'daily') {
367+
shouldRun = true;
368+
}
369+
else if (frequency === 'weekly' && week_days && week_days.includes(now.day())) {
370+
shouldRun = true;
371+
}
372+
else if (frequency === 'monthly' && day_of_month === now.date()) {
373+
shouldRun = true;
374+
}
375+
}
357376

358-
await autoTradeConfig.update({ last_execution_date: lastExecDate.toDate() });
377+
if (shouldRun) {
378+
loggerPlugin.verbose('plugins/job/scheduleAutoTrade auto trade job config (missed trade being caught up)', {
379+
id: autoTradeConfig.id,
380+
user_id,
381+
trade_hour,
382+
frequency,
383+
last_execution_date,
384+
now: now.toISOString()
385+
});
386+
try {
387+
await executeTrade(autoTradeConfig);
388+
await autoTradeConfig.update({ last_execution_date: now.clone().toDate() });
389+
} catch (err) {
390+
loggerPlugin.error(
391+
'plugins/job/scheduleAutoTrade failed to execute missed trade',
392+
{
393+
id: autoTradeConfig.id,
394+
user_id,
395+
error: err.message,
396+
trade_hour,
397+
frequency,
398+
last_execution_date,
399+
now: now.toISOString()
400+
}
401+
);
402+
}
359403
}
360404

361405
const reminderHour = (trade_hour - 12 + 24) % 24;
@@ -373,7 +417,6 @@ const scheduleAutoTrade = () => {
373417
);
374418
}
375419
}
376-
377420
} catch (err) {
378421
loggerPlugin.error('plugins/job/scheduleAutoTrade auto trade job error', err.message);
379422
}

server/utils/hollaex-tools-lib/tools/user.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3861,7 +3861,6 @@ const updateUserAutoTrade = async (user_id, {
38613861
day_of_month,
38623862
trade_hour,
38633863
active,
3864-
last_execution_date: active === false ? null : trade.last_execution_date,
38653864
description
38663865
});
38673866
};

0 commit comments

Comments
 (0)