Commit 37363b2d authored by ml's avatar ml

增加 现货、U、币合约费率相关定时任务 部分接口逻辑修改

parent 76b495db
/**
* 原文件:b024-spot.rpc.utils.js
*/
import {
ormDB,
userInfo,
coinType,
mainUserAsset,
userInfoSon,
feeRateSpotLog,
feeRateContractLog,
commonUserFeeSetting,
feeRateBaseCoinContractLog, spotPairs, contractPairs
} from "@madex/ex-ts-dao";
import { FEE_RATE_LOG_STATUS } from "../../src/constant/feeRateLogConst";
import { changeTradingFee, getPairFromCore } from "../../src/utils/coreSystemUtils";
let BigNumber = require('bignumber.js');
const logger = require('@madex/ex-js-public').logger;
let user_info = userInfo.prototype;
let coin_type = coinType.prototype;
let fee_rate_spot_log = feeRateSpotLog.prototype;
let feeRateCheckStatus = FEE_RATE_LOG_STATUS;
let WHITE_LIST: any = [];
const sleep = ms => new Promise((res) => setTimeout(res, ms));
/**
* 检查交易对是否存在
* @param pair
* @param type 1 现货 2 U本位合约 3 币本位合约
*/
let checkPair = async function (pair: string, type: number) {
let _func_name_ = 'task.fee.rate.log.model.checkPair';
if (!pair || !type) {
throw '3000';
}
let dbPair: any;
if (type == 1) {//现货
dbPair = await spotPairs.prototype.findOne({
attributes: ['id'],
where: {
symbol: String(pair),
status: 2,//提交成功
},
raw: true,
});
}
else {//U、币本位合约
dbPair = await contractPairs.prototype.findOne({
attributes: ['id'],
where: {
symbol: String(pair),
status: 2,//提交成功
},
raw: true,
})
}
if (!dbPair) {
logger.warn(_func_name_, `spot_pairs or contract_pairs no found ${pair} or no push core`);
throw '3000';
}
return dbPair;
};
let checkUser = async function (user_id) {
let _func_name_ = 'task.fee.rate.log.model.checkUser';
if (!user_id || isNaN(user_id)) {
throw '3000';
}
let dbinfo = await user_info.findOne({
attributes: ['user_id'],
where: {
user_id: Number(user_id),
},
raw: true,
});
if (!dbinfo) {
logger.warn(_func_name_, `user_info no found ${user_id}`);
throw '3000';
}
return dbinfo;
};
let checkFeeModel = async function (fee_model) {
let _func_name_ = 'task.fee.rate.log.model.checkFeeModel';
let validFeeModel = {
fixed: 1,
fixedingain: 1,
tered: 1,
tieredingain: 1,
fixedingainuser: 1,
};
if (!validFeeModel[fee_model]) {
logger.warn(_func_name_, `fee_model error ${fee_model}`);
throw '3000';
}
};
let cancelIfSpotFeeExist = async function (user_id, pair, maker_fee, taker_fee, logId) {
//TODO:原来获取正在生效的用户费率查此表 现在 ???
/* let dbFee = await DAO.spotUserFee.prototype.findOne({
where: {
user_id,
pair,
},
raw: true,
});*/
let feeExist = false;
/*if (dbFee) {
if (dbFee.maker_fee == maker_fee && dbFee.taker_fee == taker_fee) {
feeExist = true;
}
}
else if (maker_fee == 0.001 && taker_fee == 0.002) {
feeExist = true;
}*/
if (feeExist) {
throw 'fee exist';
}
}
let checkFeeRate = async function (fee_rate) {
let _func_name_ = 'spotRpcUtils.checkFeeRate';
if (isNaN(fee_rate) || Math.abs(Number(fee_rate)) > 0.005 || fee_rate < 0) {
logger.warn(_func_name_, `fee_rate error ${fee_rate}`);
throw '3000';
}
};
let cancelIfContractFeeExist = async function (user_id, pair, maker_fee, taker_fee,logId) {
//TODO:原来获取正在生效的用户费率查此表 现在 ???
/*let dbFee = await baseUUser.prototype.findOne({
where : {
user_id,
pair,
},
raw : true,
});*/
let feeExist = false;
/*if (dbFee) {
if (dbFee.maker_fee == maker_fee && dbFee.taker_fee == taker_fee) {
feeExist = true;
}
} else if (maker_fee == 0.0004 && taker_fee == 0.00060){
feeExist = true;
}*/
if (feeExist) {
throw 'fee exist';
}
}
export const changeUserSpotFee = async function (user_id, symbol, fee_model, maker_fee, taker_fee, logId) {
let is_success = true;
await checkFeeModel(fee_model);
try {
await cancelIfSpotFeeExist(user_id, symbol, maker_fee, taker_fee, logId);
}
catch (error) {
if (error == 'fee exist') {
return is_success;
}
}
let asset = await mainUserAsset.prototype.findOne({
where: {
user_id
},
raw: true
})
if (!asset) {
return is_success;
}
if (isNaN(maker_fee) || Math.abs(Number(maker_fee)) > 0.005) { // maker (-0.005, 0.005); // 正负千五
logger.warn(' task.fee.rate.log.model.changeUserSpotFee ', ` maker_fee fee_rate error ${maker_fee}`);
throw '3000';
}
if (isNaN(taker_fee) || taker_fee < 0 || taker_fee > 0.005) { // taker 最小为0
logger.warn(' task.fee.rate.log.model.changeUserSpotFee ', ` taker_fee fee_rate error ${taker_fee}`);
throw '3000';
}
await checkPair(symbol, 1);
await checkUser(user_id);
await sleep(1000);
//请求撮合 修改费率
let res = await changeTradingFee(symbol, user_id, maker_fee, taker_fee);
return res.is_success;
};
export const changeUserContractFee = async function (user_id, symbol, fee_model, maker_fee, taker_fee, logId) {
let _func_name_ = 'task.fee.rate.log.model.changeUserContractFee';
let is_success = true;
await checkPair(symbol, 2);
try {
await cancelIfContractFeeExist(user_id, symbol, maker_fee, taker_fee, logId);
}
catch (error) {
if (error == 'fee exist') {
return is_success;
}
}
let asset = await mainUserAsset.prototype.findOne({
where: {
user_id
},
raw: true
})
if (!asset) {
return is_success;
}
if (maker_fee < -0.0003) { // 最大返0.0003
logger.warn(_func_name_, `fee_rate error ${maker_fee}`);
throw '3000';
}
if (taker_fee < 0 || taker_fee > 0.005) {
logger.warn(_func_name_, `fee_rate error ${taker_fee}`);
throw '3000';
}
maker_fee = new BigNumber(String(maker_fee)).toFixed(7);
taker_fee = new BigNumber(String(taker_fee)).toFixed(7);
await checkUser(user_id);
await sleep(1000);
//请求撮合 修改费率
let res = await changeTradingFee(symbol, user_id, maker_fee, taker_fee);
return res.is_success;
};
export const isWhiteListUser = async function (user_id: number) {
let father_id = await getMainAccountUserId(user_id);
if (WHITE_LIST.includes(father_id) || Number(father_id) < 100000) {
return true;
}
return false;
}
async function getMainAccountUserId(user_id: number) {
let dbSon = await userInfoSon.prototype.findOne({
where: {
user_id: Number(user_id)
}
});
let father_id = dbSon ? dbSon.father_id : user_id;
return father_id;
}
import { ormDB, feeRateSpotLog, feeRateContractLog, commonUserFeeSetting, feeRateBaseCoinContractLog } from "@madex/ex-ts-dao";
import { FEE_STATUS } from "../../src/constant/marketMakerConst";
const logger = require('@bibox/bibox_public').logger;
let OP = ormDB.Op;
let fee_rate_spot_log = feeRateSpotLog.prototype;
let fee_rate_contract_log = feeRateContractLog.prototype;
let fee_rate_base_coin_contract_log = feeRateBaseCoinContractLog.prototype;
let common_user_fee_setting = commonUserFeeSetting.prototype;
/**
* 根据id获取币币手续费设置纪录。
* @param id
* @returns {Promise<Model>}
*/
export const spotFeeStatusCheck = async function (id) {
return await fee_rate_spot_log.findOne({
attributes: ['id', 'is_check'],
where: {
id: id,
},
raw: true,
});
};
/**
* 根据id获取合约手续费设置纪录。
* @param id
* @returns {Promise<Model>}
*/
export const contractFeeStatusCheck = async function (id) {
return await fee_rate_contract_log.findOne({
attributes: ['id', 'is_check'],
where: {
id: id,
},
raw: true,
});
};
export const baseCoinContractFeeStatusCheck = async function (id) {
return await fee_rate_base_coin_contract_log.findOne({
attributes: ['id', 'is_check'],
where: {
id: id,
},
raw: true,
});
};
/****************************************** 普通用户费率设置状态更新相关操作。 **********************************************/
/**
* 获取已提交且到开始时间的的记录。
*
* @returns {Promise<Model>}
*/
export const findUserFeeDataNeed2Active = async function () {
return await common_user_fee_setting.findAll({
where: {
begin_time: { [OP.lte]: new Date() },
status: FEE_STATUS.STATUS_FEE_SETTING_SUBMIT,
},
raw: true,
});
};
/**
* 获取已生效且到过期时间的。
*
* @returns {Promise<Model>}
*/
export const findUserFeeDataNeed2Expire = async function () {
return await common_user_fee_setting.findAll({
where: {
expire_time: { [OP.lt]: new Date() },
status: FEE_STATUS.STATUS_FEE_SETTING_EFFECTED,
},
raw: true,
});
};
/**
* 更新手续费设置纪录的状态。
* @returns {Promise<void>}
*/
export const userFeeSettingStatusUpdate = async function (id, status) {
try {
let toUpdate = {
status: status,
update_time: new Date()
};
let condition = {
id: id,
};
await common_user_fee_setting.update(toUpdate, {
where: condition
});
logger.warn("task.fee.setting.status.update.model.userFeeSettingStatusUpdate data update success.");
}
catch (e) {
logger.error("task.fee.setting.status.update.model.userFeeSettingStatusUpdate data update fail! " +
"id: %s, status: %s", id, status);
//TODO:发lark
}
};
This diff is collapsed.
import { FEE_STATUS, FEE_TYPE } from "../../src/constant/marketMakerConst";
let { logger } = require('@madex/ex-js-public');
let {
spotFeeStatusCheck, contractFeeStatusCheck, baseCoinContractFeeStatusCheck,
findUserFeeDataNeed2Active, findUserFeeDataNeed2Expire, userFeeSettingStatusUpdate
} = require('../model/task.fee.setting.status.update.model');
/**
* 币币、合约费率设置记录状态。
*/
import { FEE_RATE_LOG_STATUS } from "../../src/constant/feeRateLogConst";
/****************************************** 普通用户费率设置状态更新相关操作。 **********************************************/
/**
* 市商、普通用户、KOL 费率状态更新。
* @returns {Promise<void>}
*/
export const commonUserFeeSettingStatusUpdateService = async function (ctime = new Date()) {
try {
await commonUserStatusUpdate();
}
catch (error) {
logger.error(' commonUserFeeSettingStatusUpdate error ', error);
}
logger.warn(' commonUserFeeSettingStatusUpdate ', ctime, ' stat over ');
};
/**
* 状态扫描和更新。
* @returns {Promise<void>}
*/
async function commonUserStatusUpdate() {
let [data2Submit, data2Expire] = await Promise.all([findUserFeeDataNeed2Active(), findUserFeeDataNeed2Expire()]);
await userDataCheckAndUpdate(data2Submit);
await userDataCheckAndUpdate(data2Expire);
}
/**
* 检查数据情况并更新状态。
* @param data
* @returns {Promise<void>}
*/
async function userDataCheckAndUpdate(data) {
if (data === null || data.length === 0) {
return;
}
for (let i = 0, len = data.length; i < len; i++) {
let item = data[i];
let id = item.id;
let logIds = item.fee_log_ids;
let idArr = logIds.split(",");
if (idArr === null || idArr.length === 0) {
logger.error("commonUserFeeSettingStatusUpdate.userDataCheckAndUpdate log id parse fail! id: %s", id);
continue;
}
// 根据记录id确定该设置项的状态。
let logId = idArr[0];
let feeStatusData;
if (Number(item.type) === FEE_TYPE.FEE_TYPE_SPOT) {
feeStatusData = await spotFeeStatusCheck(logId);
}
else if (Number(item.type) === FEE_TYPE.FEE_TYPE_CONTRACT) {
feeStatusData = await contractFeeStatusCheck(logId);
}
else if (Number(item.type) === FEE_TYPE.FEE_TYPE_BASE_COIN_CONTRACT) {
feeStatusData = await baseCoinContractFeeStatusCheck(logId);
}
if (feeStatusData === null) {
logger.error("commonUserFeeSettingStatusUpdate.userDataCheckAndUpdate fee setting record miss! " +
"id: %s, logId: %s", id, logId);
continue;
}
let status = item.status;
let statusNew = status;
let feeStatus = Number(feeStatusData.is_check);
switch (feeStatus) {
case FEE_RATE_LOG_STATUS.CHECK_STATUS_ACTIVE:
statusNew = FEE_STATUS.STATUS_FEE_SETTING_EFFECTED;
break;
case FEE_RATE_LOG_STATUS.CHECK_STATUS_ACTIVE_OVER:
statusNew = FEE_STATUS.STATUS_FEE_SETTING_EXPIRE;
break;
case FEE_RATE_LOG_STATUS.CHECK_STATUS_DELETED:
statusNew = FEE_STATUS.STATUS_FEE_SETTING_DELETED;
break;
default:
continue;
}
if (statusNew !== status) {
await userFeeSettingStatusUpdate(id, statusNew);
logger.info("commonUserFeeSettingStatusUpdate.userDataCheckAndUpdate log(%s) status updated. %s -> %s",
id, status, statusNew);
}
}
}
\ No newline at end of file
...@@ -5,7 +5,7 @@ const schedule = require('node-schedule'); ...@@ -5,7 +5,7 @@ const schedule = require('node-schedule');
let { logger, datetimeUtils } = require('@madex/ex-js-public'); let { logger, datetimeUtils } = require('@madex/ex-js-public');
import { spotPairs, ormDB, coinType } from "@madex/ex-ts-dao"; import { spotPairs, ormDB, coinType } from "@madex/ex-ts-dao";
import { getPairFromCore, getCoinFromCore } from '../src/utils/coreSystemUtils' import { getPairFromCore, getCoinFromCore } from '../../src/utils/coreSystemUtils'
let running = false; let running = false;
......
import {
ormDB,
userInfoSon,
feeRateBaseCoinContractLog,
contractPairs
} from "@madex/ex-ts-dao";
import { FEE_RATE_LOG_STATUS } from "../../src/constant/feeRateLogConst";
import { changeUserContractFee, isWhiteListUser } from "../model/task.fee.rate.log.model";
const schedule = require('node-schedule');
const { logger, daoType } = require('@madex/ex-js-public');
let fee_rate_base_coin_contract_log = feeRateBaseCoinContractLog.prototype;
let feeRateCheckStatus = FEE_RATE_LOG_STATUS;
let user_info_son = userInfoSon.prototype;
let Op = ormDB.Op;
const oneHour = 1000 * 60 * 60;
const oneDay = oneHour * 24;
const oneMonth = oneDay * 30;
let inJob = false;
let limit = 3000;
/**
* 注意:
* fee_rate_spot_log
* fee_rate_contract_log
* fee_rate_base_coin_contract_log
* 相关表中不支持 all 或 ALL 交易对
* 管理后台配置用户费率的 all 交易对也是分多个交易对来处理的
* 即(common_user_fee_setting 中的 all 分多个交易对 设置到 fee_rate_log 表中)
*/
let setFeeRateJob = schedule.scheduleJob('*/30 * * * * *', function () {
if (inJob) {
return;
}
inJob = true;
doJob().catch(err => {
logger.warn('setFeeRateJob', err);
}).then(() => {
inJob = false;
});
});
let setDefaultRun = false;
let setExpiredDefaultJob = schedule.scheduleJob('*/5 * * * *', function () {
logger.info(' base coin contract setExpiredDefaultJob run ', new Date().toISOString());
if (setDefaultRun) {
return;
}
setDefaultRun = true;
setExpiredDefault().then(res => {
setDefaultRun = false;
}).catch(err => {
setDefaultRun = false;
logger.warn('base coin contract setFeeRateJob', err);
})
});
let doJob = async function () {
let ctm = new Date();
let dblogs = await fee_rate_base_coin_contract_log.findAll({
where: {
is_check: 0,
beginAt: { [Op.lte]: ctm },
expireAt: { [Op.gte]: ctm },
taker_fee: { [Op.gte]: 0.0002 },
},
limit: limit,
raw: true,
});
for (let i = 0; i < dblogs.length; i++) {
if (await isWhiteListUser(dblogs[i].user_id) && dblogs[i].comment && dblogs[i].comment.indexOf('到期') != -1) {
continue;
}
if (Number(dblogs[i].maker_fee) < 0 && (Math.abs(Number(dblogs[i].maker_fee)) > Math.abs(Number(dblogs[i].taker_fee)))) {
continue;
}
await changeOneFee(dblogs[i]);
}
await removeOldLog();
};
let changeOneFee = async function (dblog) {
let transaction;
return changeUserContractFee(dblog.user_id, dblog.pair, dblog.fee_model, dblog.maker_fee, dblog.taker_fee, dblog.id
).then(async res => {
if (!res) {
throw 'changeUserFee fail';
}
let dbsons = await user_info_son.findAll({
attributes: ['user_id', 'type'],
where: {
father_id: dblog.user_id,
// status: userInfoSon.STATUS.NORMAL, // 量化交易内部创建的账号需要变更手续费;
},
raw: true,
});
let son_fee_rate: any = [];
for (let i = 0; i < dbsons.length; i++) {
let son = dbsons[i];
son_fee_rate.push({
user_id: son.user_id,
pair: dblog.pair,
fee_model: dblog.fee_model,
maker_fee: dblog.maker_fee,
taker_fee: dblog.taker_fee,
beginAt: new Date(),
expireAt: dblog.expireAt,
is_check: feeRateCheckStatus.CHECK_STATUS_UNCHECK,
comment: '继承父账户费率',
});
}
transaction = await ormDB.transaction();
await fee_rate_base_coin_contract_log.update({ // 将当前生效中的值置为过期
is_check: feeRateCheckStatus.CHECK_STATUS_ACTIVE_OVER,
}, {
where: {
user_id: dblog.user_id,
pair: dblog.pair,
is_check: feeRateCheckStatus.CHECK_STATUS_ACTIVE,
},
transaction: transaction,
});
await fee_rate_base_coin_contract_log.update({
is_check: feeRateCheckStatus.CHECK_STATUS_ACTIVE,
}, {
where: {
id: dblog.id,
user_id: dblog.user_id,
pair: dblog.pair,
is_check: feeRateCheckStatus.CHECK_STATUS_UNCHECK,
},
transaction: transaction,
});
if (son_fee_rate.length > 0) {
await fee_rate_base_coin_contract_log.bulkCreate(son_fee_rate, {
transaction: transaction,
});
}
await transaction.commit();
transaction = null;
}).catch(async err => {
if (transaction) {
await transaction.rollback();
transaction = null;
}
logger.warn('base.coin.setFeeRateJob.changeOneFee', dblog, err);
});
};
let removeOldLog = async function () {
let ctm = Date.now();
let etm = new Date(ctm - 1000 * 60 * 60 * 24 * 31);
await fee_rate_base_coin_contract_log.destroy({
where: {
is_check: {
[Op.in]: [
feeRateCheckStatus.CHECK_STATUS_ACTIVE_OVER,
feeRateCheckStatus.CHECK_STATUS_DELETED,
]
},
updatedAt: { [Op.lt]: etm },
}
});
};
// 过期费率处理
async function setExpiredDefault() {
let comment = '费率到期系统自动调整为基础费率';
let ctm = new Date(Date.now() - oneDay); // 已经过期;
let expirdFees = await fee_rate_base_coin_contract_log.findAll({
attributes: ['user_id', 'pair', 'fee_model', 'maker_fee', 'taker_fee'],
where: {
is_check: feeRateCheckStatus.CHECK_STATUS_ACTIVE, // 正在生效中的
expireAt: { [Op.lte]: ctm },
},
limit: 500, // 后边处理插入时可以单次插入
raw: true,
});
if (expirdFees.length == 0) return;
let expiredUsers: any = [];
for (let i = 0; i < expirdFees.length; i++) {
expiredUsers.push(expirdFees[i].user_id);
}
let uncheckCounts = await fee_rate_base_coin_contract_log.findAll({
attributes: [[ormDB.literal('count(1)'), 'amount'], 'user_id'],
where: {
user_id: expiredUsers,
is_check: feeRateCheckStatus.CHECK_STATUS_UNCHECK,
beginAt: { [Op.lte]: new Date() },
comment,
},
raw: true,
group: ['user_id'],
});
let unCheckCountObj = {};
for (let i = 0; i < uncheckCounts.length; i++) {
let { user_id, amount } = uncheckCounts[i];
unCheckCountObj[user_id] = amount;
}
let defaultPairFee = await contractPairs.prototype.findAll({
attributes: ['taker_fee', 'maker_fee', 'symbol'],
where: {
status: 2
},
raw: true,
});
let defaultFeeObj = {}, max_maker_rate = 0.0004, max_taker_rate = 0.0006; // 2020.5.9
for (let i = 0; i < defaultPairFee.length; i++) {
let { symbol, maker_fee, taker_fee } = defaultPairFee[i];
defaultFeeObj[symbol] = defaultPairFee[i];
if (max_maker_rate < maker_fee) {
max_maker_rate = maker_fee;
}
if (max_taker_rate < taker_fee) {
max_taker_rate = taker_fee;
}
}
let newFeeArr: any = [];
let beginAt = new Date();
for (let i = 0; i < expirdFees.length; i++) {
let { pair, fee_model, user_id, maker_fee: before_maker_fee, taker_fee: before_taker_fee } = expirdFees[i];
if (await isWhiteListUser(user_id)) {
continue;
}
let new_maker_fee = max_maker_rate, new_taker_fee = max_taker_rate;
if (unCheckCountObj[user_id] > 0) { // 已经存在
continue;
}
if (defaultFeeObj[pair]) {
let { maker_fee, taker_fee } = defaultFeeObj[pair];
new_maker_fee = maker_fee;
new_taker_fee = taker_fee;
if (new_maker_fee === before_maker_fee && new_taker_fee === before_taker_fee) {
continue
}
}
newFeeArr.push({
user_id,
pair: pair,
fee_model,
maker_fee: new_maker_fee,
taker_fee: new_taker_fee,
beginAt: beginAt,
expireAt: new Date(beginAt.getTime() + oneMonth),
is_check: feeRateCheckStatus.CHECK_STATUS_UNCHECK,
comment,
});
}
// 如果有活动,采用活动的费率
if (newFeeArr.length > 0) {
let trans: any;
try {
trans = await ormDB.transaction();
await fee_rate_base_coin_contract_log.update({
is_check: feeRateCheckStatus.CHECK_STATUS_ACTIVE_OVER,
}, {
where: {
user_id: expiredUsers,
is_check: feeRateCheckStatus.CHECK_STATUS_ACTIVE, // 正在生效中的
expireAt: { [Op.lte]: ctm },
},
transaction: trans,
});
await fee_rate_base_coin_contract_log.bulkCreate(newFeeArr, {
transaction: trans,
});
await trans.commit();
trans = null;
}
catch (error) {
if (trans) {
trans.rollback();
}
}
}
}
import {
ormDB,
userInfoSon,
feeRateContractLog,
contractPairs
} from "@madex/ex-ts-dao";
import { FEE_RATE_LOG_STATUS } from "../../src/constant/feeRateLogConst";
import { changeUserContractFee, isWhiteListUser } from "../model/task.fee.rate.log.model";
const schedule = require('node-schedule');
const { logger, daoType } = require('@madex/ex-js-public');
let fee_rate_contract_log = feeRateContractLog.prototype;
let feeRateCheckStatus = FEE_RATE_LOG_STATUS;
let user_info_son = userInfoSon.prototype;
let Op = ormDB.Op;
const oneHour = 1000 * 60 * 60;
const oneDay = oneHour * 24;
const oneMonth = oneDay * 30;
let inJob = false;
let limit = 3000;
/**
* 注意:
* fee_rate_spot_log
* fee_rate_contract_log
* fee_rate_base_coin_contract_log
* 相关表中不支持 all 或 ALL 交易对
* 管理后台配置用户费率的 all 交易对也是分多个交易对来处理的
* 即(common_user_fee_setting 中的 all 分多个交易对 设置到 fee_rate_log 表中)
*/
let setFeeRateJob = schedule.scheduleJob('*/30 * * * * *', function () {
if (inJob) {
return;
}
inJob = true;
doJob().catch(err => {
logger.warn('setFeeRateJob', err);
}).then(() => {
inJob = false;
});
});
let setDefaultRun = false;
let setExpiredDefaultJob = schedule.scheduleJob('*/5 * * * *', function () {
logger.info(' contract setExpiredDefaultJob run ', new Date().toISOString());
if (setDefaultRun) {
return;
}
setDefaultRun = true;
setExpiredDefault().then(res => {
setDefaultRun = false;
}).catch(err => {
setDefaultRun = false;
logger.warn('contract setFeeRateJob', err);
})
});
let doJob = async function () {
let ctm = new Date();
let dblogs = await fee_rate_contract_log.findAll({
where: {
is_check: 0,
beginAt: { [Op.lte]: ctm },
expireAt: { [Op.gte]: ctm },
},
limit: limit,
raw: true,
});
for (let i = 0; i < dblogs.length; i++) {
if (await isWhiteListUser(dblogs[i].user_id) && dblogs[i].comment && dblogs[i].comment.indexOf('到期') != -1) {
continue;
}
if (Number(dblogs[i].maker_fee) < 0 && (Math.abs(Number(dblogs[i].maker_fee)) > Math.abs(Number(dblogs[i].taker_fee)))) {
continue;
}
await changeOneFee(dblogs[i]);
}
await removeOldLog();
};
let changeOneFee = async function (dblog) {
let transaction;
return changeUserContractFee(dblog.user_id, dblog.pair, dblog.fee_model, dblog.maker_fee, dblog.taker_fee, dblog.id
).then(async res => {
if (!res) {
throw 'changeUserFee fail';
}
let dbsons = await user_info_son.findAll({
attributes: ['user_id', 'type'],
where: {
father_id: dblog.user_id,
// status: userInfoSon.STATUS.NORMAL, // 量化交易内部创建的账号需要变更手续费;
},
raw: true,
});
let son_fee_rate: any = [];
for (let i = 0; i < dbsons.length; i++) {
let son = dbsons[i];
son_fee_rate.push({
user_id: son.user_id,
pair: dblog.pair,
fee_model: dblog.fee_model,
maker_fee: dblog.maker_fee,
taker_fee: dblog.taker_fee,
beginAt: new Date(),
expireAt: dblog.expireAt,
is_check: feeRateCheckStatus.CHECK_STATUS_UNCHECK,
comment: '继承父账户费率',
});
}
transaction = await ormDB.transaction();
await fee_rate_contract_log.update({ // 将当前生效中的值置为过期
is_check: feeRateCheckStatus.CHECK_STATUS_ACTIVE_OVER,
}, {
where: {
user_id: dblog.user_id,
pair: dblog.pair,
is_check: feeRateCheckStatus.CHECK_STATUS_ACTIVE,
},
transaction: transaction,
});
await fee_rate_contract_log.update({
is_check: feeRateCheckStatus.CHECK_STATUS_ACTIVE,
}, {
where: {
id: dblog.id,
user_id: dblog.user_id,
pair: dblog.pair,
is_check: feeRateCheckStatus.CHECK_STATUS_UNCHECK,
},
transaction: transaction,
});
if (son_fee_rate.length > 0) {
await fee_rate_contract_log.bulkCreate(son_fee_rate, {
transaction: transaction,
});
}
await transaction.commit();
transaction = null;
}).catch(async err => {
if (transaction) {
await transaction.rollback();
transaction = null;
}
logger.warn('setFeeRateJob.changeOneFee', dblog, err);
});
};
let removeOldLog = async function () {
let ctm = Date.now();
let etm = new Date(ctm - 1000 * 60 * 60 * 24 * 31);
await fee_rate_contract_log.destroy({
where: {
is_check: {
[Op.in]: [
feeRateCheckStatus.CHECK_STATUS_ACTIVE_OVER,
feeRateCheckStatus.CHECK_STATUS_DELETED,
]
},
updatedAt: { [Op.lt]: etm },
}
});
};
// 过期费率处理
async function setExpiredDefault() {
let comment = '费率到期系统自动调整为基础费率';
let ctm = new Date(Date.now() - oneDay); // 已经过期;
let expirdFees = await fee_rate_contract_log.findAll({
attributes: ['user_id', 'pair', 'fee_model', 'maker_fee', 'taker_fee'],
where: {
is_check: feeRateCheckStatus.CHECK_STATUS_ACTIVE, // 正在生效中的
expireAt: { [Op.lte]: ctm },
},
limit: 500, // 后边处理插入时可以单次插入
raw: true,
});
if (expirdFees.length == 0) return;
let expiredUsers: any = [];
for (let i = 0; i < expirdFees.length; i++) {
expiredUsers.push(expirdFees[i].user_id);
}
let uncheckCounts = await fee_rate_contract_log.findAll({
attributes: [[ormDB.literal('count(1)'), 'amount'], 'user_id'],
where: {
user_id: expiredUsers,
is_check: feeRateCheckStatus.CHECK_STATUS_UNCHECK,
beginAt: { [Op.lte]: new Date() },
comment,
},
raw: true,
group: ['user_id'],
});
let unCheckCountObj = {};
for (let i = 0; i < uncheckCounts.length; i++) {
let { user_id, amount } = uncheckCounts[i];
unCheckCountObj[user_id] = amount;
}
let defaultPairFee = await contractPairs.prototype.findAll({
attributes: ['taker_fee', 'maker_fee', 'symbol'],
where: {
status: 2
},
raw: true,
});
let defaultFeeObj = {}, max_maker_rate = 0.0004, max_taker_rate = 0.0006; // 2020.5.9
for (let i = 0; i < defaultPairFee.length; i++) {
let { symbol, maker_fee, taker_fee } = defaultPairFee[i];
defaultFeeObj[symbol] = defaultPairFee[i];
if (max_maker_rate < maker_fee) {
max_maker_rate = maker_fee;
}
if (max_taker_rate < taker_fee) {
max_taker_rate = taker_fee;
}
}
let newFeeArr: any = [];
let beginAt = new Date();
for (let i = 0; i < expirdFees.length; i++) {
let { pair, fee_model, user_id, maker_fee: before_maker_fee, taker_fee: before_taker_fee } = expirdFees[i];
let new_maker_fee = max_maker_rate, new_taker_fee = max_taker_rate;
if (await isWhiteListUser(user_id)) {
continue;
}
if (unCheckCountObj[user_id] > 0) { // 已经存在
continue;
}
if (defaultFeeObj[pair]) {
let { maker_fee, taker_fee } = defaultFeeObj[pair];
new_maker_fee = maker_fee;
new_taker_fee = taker_fee;
if (new_maker_fee === before_maker_fee && new_taker_fee === before_taker_fee) {
continue
}
}
newFeeArr.push({
user_id,
pair: pair,
fee_model,
maker_fee: new_maker_fee,
taker_fee: new_taker_fee,
beginAt: beginAt,
expireAt: new Date(beginAt.getTime() + oneMonth),
is_check: feeRateCheckStatus.CHECK_STATUS_UNCHECK,
comment,
});
}
// 如果有活动,采用活动的费率
if (newFeeArr.length > 0) {
let trans: any;
try {
trans = await ormDB.transaction();
await fee_rate_contract_log.update({
is_check: feeRateCheckStatus.CHECK_STATUS_ACTIVE_OVER,
}, {
where: {
user_id: expiredUsers,
is_check: feeRateCheckStatus.CHECK_STATUS_ACTIVE, // 正在生效中的
expireAt: { [Op.lte]: ctm },
},
transaction: trans,
});
await fee_rate_contract_log.bulkCreate(newFeeArr, {
transaction: trans,
});
await trans.commit();
trans = null;
}
catch (error) {
if (trans) {
trans.rollback();
}
}
}
}
This diff is collapsed.
/* ======================================================================
* 市商、普通用户、KOL费率设置纪录状态更新。
* ====================================================================== */
import { commonUserFeeSettingStatusUpdateService } from "../service/task.fee.setting.status.update.service";
let schedule = require('node-schedule');
let { logger } = require('@madex/ex-js-public');
let userSettingUpdateRunning = false;
/**
* 市商、普通用户、KOL 费率设置纪录状态更新。
* 每10分钟更新一次。
*/
let userSettingStatusUpdate = schedule.scheduleJob('0 */10 * * * *', async function () {
try {
logger.info('task_fee_setting_status_update userSettingStatusUpdate start');
if (!userSettingUpdateRunning) {
userSettingUpdateRunning = true;
await commonUserFeeSettingStatusUpdateService();
userSettingUpdateRunning = false;
}
}
catch (error) {
userSettingUpdateRunning = false;
logger.warn('task_fee_setting_status_update userSettingStatusUpdate error', error);
}
});
\ No newline at end of file
/*
import { statisProjectMakerDeals } from "../service/marketMakerMgr.service";
const schedule = require('node-schedule');
const logger = require('@madex/ex-js-public').logger;
let subModel = {};
module.exports = subModel;
// 统计项目方做市商成交量信息,并设置费率,
let inJob = false;
let setFeeRateJob = schedule.scheduleJob('0 10 0 * * *', async function () {
if (inJob) {
return;
}
inJob = true;
try {
await statisProjectMakerDeals();
inJob = false;
} catch (error) {
inJob = false;
logger.warn(' 统计项目方做市商成交量 error', error);
}
});*/
...@@ -153,31 +153,32 @@ export async function add(commonUserFeeVO: CommonUserFeeVO, currentUserId: any, ...@@ -153,31 +153,32 @@ export async function add(commonUserFeeVO: CommonUserFeeVO, currentUserId: any,
let pair = dbInfo.pair; let pair = dbInfo.pair;
let type = dbInfo.type; let type = dbInfo.type;
let now = new Date(); let now = new Date();
let insertDbOne: any = []; let insertDbList: any = [];
let rateLog = buildSubmitItem(pair, dbInfo, now, dbInfo.user_channel);
let rateLogs = await buildSubmitItems(pair, dbInfo, now, dbInfo.user_channel, type);
//提交到log表 //提交到log表
if (type == FEE_TYPE.FEE_TYPE_SPOT) { if (type == FEE_TYPE.FEE_TYPE_SPOT) {
insertDbOne = await feeRateSpotLog.prototype.create(rateLog, { insertDbList = await feeRateSpotLog.prototype.bulkCreate(rateLogs, {
transaction: tx transaction: tx
}); });
} }
else if (type == FEE_TYPE.FEE_TYPE_BASE_COIN_CONTRACT) {//币本位 else if (type == FEE_TYPE.FEE_TYPE_BASE_COIN_CONTRACT) {//币本位
insertDbOne = await feeRateBaseCoinContractLog.prototype.create(rateLog, { insertDbList = await feeRateBaseCoinContractLog.prototype.bulkCreate(rateLogs, {
transaction: tx transaction: tx
}); });
} }
else {//U本位 else {//U本位
insertDbOne = await feeRateContractLog.prototype.create(rateLog, { insertDbList = await feeRateContractLog.prototype.bulkCreate(rateLogs, {
transaction: tx transaction: tx
}); });
} }
let feeLogId = insertDbOne.id; let ids = insertDbList.map(item => item.id);
await commonUserFeeSetting.prototype.update({ await commonUserFeeSetting.prototype.update({
fee_log_ids: feeLogId, fee_log_ids: ids.toString(),
update_time: new Date() update_time: new Date()
}, { }, {
where: { where: {
...@@ -224,34 +225,34 @@ export async function update(commonUserFeeVO: CommonUserFeeVO, currentUserId: an ...@@ -224,34 +225,34 @@ export async function update(commonUserFeeVO: CommonUserFeeVO, currentUserId: an
let tx; let tx;
try { try {
tx = await ormDB.transaction(); tx = await ormDB.transaction();
let feeLogId: any; let feeLogIds: any;
//这四项修改需要 重新写入 rate_log //这四项修改需要 重新写入 rate_log
if (commonUserFeeVO.maker_fee != dbInfo.maker_fee || commonUserFeeVO.taker_fee != dbInfo.taker_fee if (commonUserFeeVO.maker_fee != dbInfo.maker_fee || commonUserFeeVO.taker_fee != dbInfo.taker_fee
|| commonUserFeeVO.begin_time != dbInfo.begin_time || commonUserFeeVO.expire_time != dbInfo.expire_time) { || commonUserFeeVO.begin_time != dbInfo.begin_time || commonUserFeeVO.expire_time != dbInfo.expire_time) {
let insertDbOne: any; let insertDbList: any;
let rateLog = buildSubmitItem(pair, commonUserFeeVO, new Date(), Number(commonUserFeeVO.user_channel)); let rateLogs = await buildSubmitItems(pair, commonUserFeeVO, new Date(), Number(commonUserFeeVO.user_channel), type);
//提交到log表 //提交到log表
if (type == FEE_TYPE.FEE_TYPE_SPOT) { if (type == FEE_TYPE.FEE_TYPE_SPOT) {
insertDbOne = await feeRateSpotLog.prototype.create(rateLog, { insertDbList = await feeRateSpotLog.prototype.bulkCreate(rateLogs, {
transaction: tx transaction: tx
}); });
} }
else if (type == FEE_TYPE.FEE_TYPE_BASE_COIN_CONTRACT) {//币本位 else if (type == FEE_TYPE.FEE_TYPE_BASE_COIN_CONTRACT) {//币本位
insertDbOne = await feeRateBaseCoinContractLog.prototype.create(rateLog, { insertDbList = await feeRateBaseCoinContractLog.prototype.bulkCreate(rateLogs, {
transaction: tx transaction: tx
}); });
} }
else {//U本位 else {//U本位
insertDbOne = await feeRateContractLog.prototype.create(rateLog, { insertDbList = await feeRateContractLog.prototype.bulkCreate(rateLogs, {
transaction: tx transaction: tx
}); });
} }
feeLogId = insertDbOne.id;
feeLogIds = insertDbList.map(item => item.id);
} }
let dbFeeLogIdsArr = dbInfo.fee_log_ids.split(",");
dbFeeLogIdsArr.push(String(feeLogId));
await commonUserFeeSetting.prototype.update({ await commonUserFeeSetting.prototype.update({
maker_fee: Number(commonUserFeeVO.maker_fee), maker_fee: Number(commonUserFeeVO.maker_fee),
taker_fee: Number(commonUserFeeVO.taker_fee), taker_fee: Number(commonUserFeeVO.taker_fee),
...@@ -263,7 +264,7 @@ export async function update(commonUserFeeVO: CommonUserFeeVO, currentUserId: an ...@@ -263,7 +264,7 @@ export async function update(commonUserFeeVO: CommonUserFeeVO, currentUserId: an
amount_require_usdt: commonUserFeeVO.amount_require_usdt, amount_require_usdt: commonUserFeeVO.amount_require_usdt,
applicant: commonUserFeeVO.applicant, applicant: commonUserFeeVO.applicant,
update_time: new Date(), update_time: new Date(),
fee_log_ids: feeLogId ? dbFeeLogIdsArr.toString() : dbInfo.fee_log_ids, fee_log_ids: feeLogIds ? feeLogIds.toString() : dbInfo.fee_log_ids,
}, { }, {
where: { where: {
id: Number(commonUserFeeVO.id) id: Number(commonUserFeeVO.id)
...@@ -460,10 +461,25 @@ async function getDbFeeSetting(user_id: number | any, type: number | any, user_c ...@@ -460,10 +461,25 @@ async function getDbFeeSetting(user_id: number | any, type: number | any, user_c
return dbInfo; return dbInfo;
} }
function buildSubmitItem(pair: string, dbInfo: any, now: Date, user_channel: number) { async function buildSubmitItems(pair: string, dbInfo: any, now: Date, user_channel: number, type: number) {
let pairList: any;
if (pair == 'all') {
if (type == FEE_TYPE.FEE_TYPE_SPOT) {
pairList = await getAllSpotPairs();
}
else {
pairList = await getAllContractPairs();
}
}
else {
pairList = [pair]
}
let itemList: any = [];
for (let onePair of pairList) {
let item = { let item = {
user_id: dbInfo.user_id, user_id: dbInfo.user_id,
pair: pair, pair: onePair,
fee_model: FEE_MODEL_SPOT_DEFAULT, fee_model: FEE_MODEL_SPOT_DEFAULT,
maker_fee: dbInfo.maker_fee, maker_fee: dbInfo.maker_fee,
taker_fee: dbInfo.taker_fee, taker_fee: dbInfo.taker_fee,
...@@ -484,8 +500,11 @@ function buildSubmitItem(pair: string, dbInfo: any, now: Date, user_channel: num ...@@ -484,8 +500,11 @@ function buildSubmitItem(pair: string, dbInfo: any, now: Date, user_channel: num
else { else {
item.comment = COMMENT_USER_FEE_SUBMIT item.comment = COMMENT_USER_FEE_SUBMIT
} }
itemList.push(item);
}
return item;
return itemList;
} }
async function checkSpotPair(pair: string) { async function checkSpotPair(pair: string) {
...@@ -537,3 +556,34 @@ async function getProjectMakerTradeStat(user_id: number, pair: string) { ...@@ -537,3 +556,34 @@ async function getProjectMakerTradeStat(user_id: number, pair: string) {
return res; return res;
} }
async function getAllSpotPairs() {
let dbPairs = await spotPairs.prototype.findAll(
{
attributes: ['symbol'],
where: {
status: 2
},
raw: true
}
);
return dbPairs.map(item => item.symbol);
}
async function getAllContractPairs() {
let dbPairs = await contractPairs.prototype.findAll(
{
attributes: ['symbol'],
where: {
status: 2
},
raw: true
}
);
return dbPairs.map(item => item.symbol);
}
...@@ -41,10 +41,11 @@ export interface NoticePageVO extends NoticeVO { ...@@ -41,10 +41,11 @@ export interface NoticePageVO extends NoticeVO {
export async function list(noticePageVO: NoticePageVO) { export async function list(noticePageVO: NoticePageVO) {
let where = Object.create(null); let where = Object.create(null);
where.del_sign = 0;
if (noticePageVO.publish_flag) { if (noticePageVO.publish_flag) {
where.publish_flag = noticePageVO.publish_flag; where.publish_flag = noticePageVO.publish_flag;
} }
if (Number(noticePageVO.user_id) >= 0) { if (noticePageVO.user_id && Number(noticePageVO.user_id) >= 0) {
where.user_id = noticePageVO.user_id; where.user_id = noticePageVO.user_id;
} }
if (noticePageVO.notice_type) { if (noticePageVO.notice_type) {
...@@ -57,9 +58,6 @@ export async function list(noticePageVO: NoticePageVO) { ...@@ -57,9 +58,6 @@ export async function list(noticePageVO: NoticePageVO) {
let date = datetimeUtils.trim(noticePageVO.push_time, 's'); let date = datetimeUtils.trim(noticePageVO.push_time, 's');
where.push_time = { [ormDB.Op.gte]: date }; where.push_time = { [ormDB.Op.gte]: date };
} }
if (noticePageVO.del_sign || noticePageVO.del_sign === 0) {
where.del_sign = noticePageVO.del_sign;
}
if (noticePageVO.status) { if (noticePageVO.status) {
where.status = noticePageVO.status; where.status = noticePageVO.status;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment