UNPKG

@tomei/live-price

Version:

Tomei live-price Package

395 lines 19.2 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SourceFeed = void 0; const general_1 = require("@tomei/general"); const feed_cut_off_history_1 = require("../feed-cut-off-history/feed-cut-off-history"); const source_feed_repository_1 = require("./source-feed.repository"); const feed_enum_1 = require("../../enum/feed.enum"); const feed_history_1 = require("../feed-history/feed-history"); const feed_1 = require("../feed/feed"); const feed_history_repository_1 = require("../feed-history/feed-history.repository"); const sequelize_1 = require("sequelize"); const sso_1 = require("@tomei/sso"); const activity_history_1 = require("@tomei/activity-history"); class SourceFeed extends feed_1.Feed { constructor(sourcefeedAttr, feedAttr) { super(feedAttr); if (sourcefeedAttr) { this.FeedName = sourcefeedAttr.FeedName; this.Status = sourcefeedAttr.Status; this.IsSourceFeedAvailableYN = sourcefeedAttr.IsSourceFeedAvailableYN; this.IsFeedCutOffYN = sourcefeedAttr.IsFeedCutOffYN; this.CurrentCutOffHistoryId = sourcefeedAttr.CurrentCutOffHistoryId; this.AutomaticCutOffVariance = sourcefeedAttr.AutomaticCutOffVariance; this.AutomaticCutOffMinutes = sourcefeedAttr.AutomaticCutOffMinutes; } } static init(dbTransaction, FeedName) { return __awaiter(this, void 0, void 0, function* () { try { if (FeedName) { const sourcefeed = yield SourceFeed._SourceRepo.findByPk(FeedName, dbTransaction); const feed = yield feed_1.Feed._Repo.findByPk(FeedName, dbTransaction); if (sourcefeed) { return new SourceFeed(sourcefeed, feed); } else { throw new general_1.ClassError('SourceFeed', 'FeedErrMsg00', 'Feed Not Found'); } } return new SourceFeed(); } catch (error) { throw new general_1.ClassError('SourceFeed', 'FeedErrMsg01', error.message); } }); } save(dbTransaction) { const _super = Object.create(null, { save: { get: () => super.save } }); return __awaiter(this, void 0, void 0, function* () { try { yield _super.save.call(this, dbTransaction); const sourcefeed = yield SourceFeed._SourceRepo.findOne({ where: { FeedName: this.FeedName, }, transaction: dbTransaction, }); const payload = { FeedName: this.FeedName, Status: this.Status, IsSourceFeedAvailableYN: this.IsSourceFeedAvailableYN, IsFeedCutOffYN: this.IsFeedCutOffYN, CurrentCutOffHistoryId: this.CurrentCutOffHistoryId, AutomaticCutOffVariance: this.AutomaticCutOffVariance, AutomaticCutOffMinutes: this.AutomaticCutOffMinutes, }; if (sourcefeed) { yield SourceFeed._SourceRepo.update(payload, { where: { FeedName: this.FeedName, }, transaction: dbTransaction, }); } else { yield SourceFeed._SourceRepo.create(payload, { transaction: dbTransaction, }); } } catch (error) { throw new general_1.ClassError('Feed', 'FeedErrMsg02', error.message); } }); } getCutOffDetails(dbTransaction) { return __awaiter(this, void 0, void 0, function* () { try { if (this.CurrentCutOffHistoryId) { return yield feed_cut_off_history_1.FeedCutOffHistory.init(this.CurrentCutOffHistoryId, dbTransaction); } return null; } catch (error) { throw new general_1.ClassError('Feed', 'FeedErrMsg03', error.message); } }); } recordFeedPrice(priceData, dbTransaction) { return __awaiter(this, void 0, void 0, function* () { try { const feedName = this.FeedName; const sourceFeedBuyPrice = priceData.BuyPrice; const sourceFeedSellPrice = priceData.SellPrice; let FeedBuyPrice; let FeedSellPrice; let IsManualCutOffYN = 'N'; let IsCircuitBreakerActivatedYN = 'N'; if (this.IsManualPriceActivatedYN === 'Y') { const manualPriceHistory = yield feed_history_1.FeedHistory.getLatestPrice(this.FeedName, this.FeedName.split('/')[1], null, dbTransaction); FeedBuyPrice = manualPriceHistory.FeedBuyPrice; FeedSellPrice = manualPriceHistory.FeedSellPrice; } else if (this.IsFeedCutOffYN === 'Y') { FeedBuyPrice = 0; FeedSellPrice = 0; const feedCutOffHistory = yield feed_cut_off_history_1.FeedCutOffHistory.init(this.CurrentCutOffHistoryId, dbTransaction); if (feedCutOffHistory.ActivationTrigger === feed_enum_1.ActivationTrigger.MANUAL) { IsManualCutOffYN = 'Y'; } else { IsCircuitBreakerActivatedYN = 'Y'; } } else { FeedBuyPrice = priceData.SellPrice; FeedSellPrice = priceData.SellPrice; } const isSourceFeedAvailableYN = priceData.IsSourceFeedAvailableYN; const isManualPriceActivatedYN = this.IsManualPriceActivatedYN; let feedHistory = yield feed_history_1.FeedHistory.init(dbTransaction); feedHistory = yield feedHistory.saveFeedPrice({ FeedName: feedName, DateTime: new Date(), Currency: priceData.Currency, SourceFeedBuyPrice: sourceFeedBuyPrice, SourceFeedSellPrice: sourceFeedSellPrice, FeedBuyPrice: FeedBuyPrice, FeedSellPrice: FeedSellPrice, IsSourceFeedAvailableYN: isSourceFeedAvailableYN, IsCircuitBreakerActivatedYN: IsCircuitBreakerActivatedYN, IsManualPriceActivatedYN: isManualPriceActivatedYN, IsManualCutOffYN: IsManualCutOffYN, }, dbTransaction); if (FeedBuyPrice !== 0 && FeedSellPrice !== 0) { this.Status = 'Available'; } else { this.Status = 'Unavailable'; } yield this.save(dbTransaction); return feedHistory; } catch (error) { throw error; } }); } getPreviousSourceFeedConfig(dbTransaction) { return __awaiter(this, void 0, void 0, function* () { try { const previousActivity = yield SourceFeed._ActivityRepo.findOne({ where: { EntityType: 'SourceFeed', EntityId: this.FeedName, Action: activity_history_1.ActionEnum.UPDATE, Description: 'Update Circuit Breaker Config for :' + this.FeedName, }, transaction: dbTransaction, order: [['PerformedAt', 'DESC']], }); if (previousActivity) { const previousConfig = JSON.parse(previousActivity.EntityValueBefore); return { AutomaticCutOffVariance: previousConfig.AutomaticCutOffVariance, AutomaticCutOffMinutes: previousConfig.AutomaticCutOffMinutes, UpdatedAt: previousActivity.PerformedAt, }; } return false; } catch (error) { throw error; } }); } circuitBreakerCheck(priceData, priceSource, dbTransaction) { return __awaiter(this, void 0, void 0, function* () { try { let automaticCutOffVariance = this.AutomaticCutOffVariance; let automaticCutOffMinutes = this.AutomaticCutOffMinutes; const previousConfig = yield this.getPreviousSourceFeedConfig(dbTransaction); if (previousConfig) { const currentTime = new Date().getTime(); const previousConfigUpdatedTime = previousConfig.UpdatedAt.getTime(); const currentConfigTimeWindow = automaticCutOffMinutes * 60000; const effectiveStartTime = Math.max(previousConfigUpdatedTime + currentConfigTimeWindow, currentTime); if (currentTime < effectiveStartTime) { automaticCutOffVariance = previousConfig.AutomaticCutOffVariance; automaticCutOffMinutes = previousConfig.AutomaticCutOffMinutes; } else { automaticCutOffVariance = this.AutomaticCutOffVariance; automaticCutOffMinutes = this.AutomaticCutOffMinutes; } } else { automaticCutOffVariance = this.AutomaticCutOffVariance; automaticCutOffMinutes = this.AutomaticCutOffMinutes; } const feedHistories = yield SourceFeed._FeedHistoryRepo.findAll({ where: { FeedName: this.FeedName, DateTime: { [sequelize_1.Op.gte]: new Date(new Date().getTime() - this.AutomaticCutOffMinutes * 60000), }, }, order: [['DateTime', 'DESC']], transaction: dbTransaction, }); if (feedHistories.some(({ IsManualPriceActivatedYN }) => IsManualPriceActivatedYN === 'Y')) { return true; } const validFeedHistories = feedHistories.filter(({ SourceFeedBuyPrice, SourceFeedSellPrice }) => SourceFeedBuyPrice !== 0 && SourceFeedSellPrice !== 0); if (validFeedHistories.length === 0) return true; const buyPrices = validFeedHistories.map(({ SourceFeedBuyPrice }) => SourceFeedBuyPrice); const sellPrices = validFeedHistories.map(({ SourceFeedSellPrice }) => SourceFeedSellPrice); buyPrices.push(priceData.BuyPrice); sellPrices.push(priceData.SellPrice); const [minBuyPrice, maxBuyPrice] = [ Math.min(...buyPrices), Math.max(...buyPrices), ]; const [minSellPrice, maxSellPrice] = [ Math.min(...sellPrices), Math.max(...sellPrices), ]; const buyVariance = ((maxBuyPrice - minBuyPrice) / minBuyPrice) * 100; const sellVariance = ((maxSellPrice - minSellPrice) / minSellPrice) * 100; if ((buyVariance > this.AutomaticCutOffVariance || sellVariance > this.AutomaticCutOffVariance) && this.IsFeedCutOffYN === 'N') { yield this.cutOff(priceSource, dbTransaction); return false; } return true; } catch (error) { throw error; } }); } cutOff(priceSource, dbTransaction, activatedById) { return __awaiter(this, void 0, void 0, function* () { try { let feedCutOffHistory = yield feed_cut_off_history_1.FeedCutOffHistory.init(); feedCutOffHistory.FeedName = this.FeedName; let activatedBy = null; let isManualCutOff = 'N'; let isCircuitBreakerActivated = 'N'; if (activatedById) { const user = yield sso_1.LoginUser.init(null, parseInt(activatedById)); activatedBy = user.FullName; feedCutOffHistory.ActivationTrigger = feed_enum_1.ActivationTrigger.MANUAL; isManualCutOff = 'Y'; } else { feedCutOffHistory.ActivationTrigger = feed_enum_1.ActivationTrigger.LIMIT_BREACH; isCircuitBreakerActivated = 'Y'; } feedCutOffHistory = yield feedCutOffHistory.create(dbTransaction, activatedById); let feedHistory = yield feed_history_1.FeedHistory.init(dbTransaction); const fetchResult = yield priceSource.fetchPrice({ [this.FeedName]: this, }); const priceData = fetchResult[this.FeedName]; feedHistory = yield feedHistory.saveFeedPrice({ FeedName: this.FeedName, DateTime: new Date(), Currency: priceData.Currency, SourceFeedBuyPrice: priceData.BuyPrice, SourceFeedSellPrice: priceData.SellPrice, FeedBuyPrice: 0, FeedSellPrice: 0, IsSourceFeedAvailableYN: priceData.IsSourceFeedAvailableYN, IsManualCutOffYN: isManualCutOff, IsCircuitBreakerActivatedYN: isCircuitBreakerActivated, IsManualPriceActivatedYN: 'N', }, dbTransaction); yield this.createTomeiPriceHistory(feedHistory, dbTransaction); this.IsFeedCutOffYN = 'Y'; this.CurrentCutOffHistoryId = feedCutOffHistory.FeedCutOffHistoryId; yield this.save(dbTransaction); } catch (error) { throw error; } }); } deactivateCutOff(priceSource, dbTransaction, deactivatedById) { return __awaiter(this, void 0, void 0, function* () { try { yield feed_cut_off_history_1.FeedCutOffHistory.deactivate(this.FeedName, deactivatedById, dbTransaction); this.IsFeedCutOffYN = 'N'; yield this.save(dbTransaction); const fetchResult = yield priceSource.fetchPrice({ [this.FeedName]: this, }); const priceData = fetchResult[this.FeedName]; const feedHistory = yield this.recordFeedPrice(priceData, dbTransaction); yield this.createTomeiPriceHistory(feedHistory, dbTransaction); } catch (error) { throw error; } }); } updateCircuitBreakerConfig(AutomaticCutOffVariance, AutomaticCutOffMinutes, dbTransaction, loginUser) { return __awaiter(this, void 0, void 0, function* () { try { const EntityValueBefore = { AutomaticCutOffVariance: this.AutomaticCutOffVariance, AutomaticCutOffMinutes: this.AutomaticCutOffMinutes, FeedName: this.FeedName, Status: this.Status, IsSourceFeedAvailableYN: this.IsSourceFeedAvailableYN, IsFeedCutOffYN: this.IsFeedCutOffYN, CurrentCutOffHistoryId: this.CurrentCutOffHistoryId, }; this.AutomaticCutOffVariance = AutomaticCutOffVariance; this.AutomaticCutOffMinutes = AutomaticCutOffMinutes; yield SourceFeed._SourceRepo.update({ AutomaticCutOffVariance: this.AutomaticCutOffVariance, AutomaticCutOffMinutes: this.AutomaticCutOffMinutes, }, { where: { FeedName: this.FeedName, }, transaction: dbTransaction, }); const activity = new activity_history_1.Activity(); activity.ActivityId = activity.createId(); activity.Description = 'Update Circuit Breaker Config for :' + this.FeedName; activity.Action = activity_history_1.ActionEnum.UPDATE; activity.EntityType = 'SourceFeed'; activity.EntityId = this.FeedName; activity.EntityValueBefore = JSON.stringify(EntityValueBefore); activity.EntityValueAfter = JSON.stringify({ AutomaticCutOffVariance: this.AutomaticCutOffVariance, AutomaticCutOffMinutes: this.AutomaticCutOffMinutes, FeedName: this.FeedName, Status: this.Status, IsSourceFeedAvailableYN: this.IsSourceFeedAvailableYN, IsFeedCutOffYN: this.IsFeedCutOffYN, CurrentCutOffHistoryId: this.CurrentCutOffHistoryId, }); yield activity.create(loginUser.ObjectId, dbTransaction); } catch (error) { throw error; } }); } static getAllSourceFeed(dbTransaction) { return __awaiter(this, void 0, void 0, function* () { try { const sourceFeeds = yield SourceFeed._SourceRepo.findAll({ transaction: dbTransaction, }); return sourceFeeds.map((sourceFeed) => new SourceFeed(sourceFeed)); } catch (error) { throw error; } }); } } exports.SourceFeed = SourceFeed; SourceFeed._SourceRepo = new source_feed_repository_1.SourceFeedRepository(); SourceFeed._FeedHistoryRepo = new feed_history_repository_1.FeedHistoryRepository(); SourceFeed._ActivityRepo = new activity_history_1.ActivityHistoryRepository(); //# sourceMappingURL=source-feed.js.map