From 1c8225346398eede95d5a8ddf3c7e61c6aa1af11 Mon Sep 17 00:00:00 2001 From: Mario Cao Date: Mon, 9 May 2022 10:10:23 +0200 Subject: [PATCH] fix(pushpair): Fetch Last Update now returns oldest pair update --- .../PairDeviationCheckerModule.ts | 16 ++-- src/modules/pushPair/PushPairModule.ts | 7 +- .../services/FetchLastUpdateService.ts | 89 ++++++++++++------- 3 files changed, 70 insertions(+), 42 deletions(-) diff --git a/src/modules/pairDeviationChecker/PairDeviationCheckerModule.ts b/src/modules/pairDeviationChecker/PairDeviationCheckerModule.ts index 37ea470..34d5391 100644 --- a/src/modules/pairDeviationChecker/PairDeviationCheckerModule.ts +++ b/src/modules/pairDeviationChecker/PairDeviationCheckerModule.ts @@ -1,19 +1,20 @@ import Big from "big.js"; +import logger from "../../services/LoggerService"; +import { AppConfig } from "../../models/AppConfig"; import { ENABLE_TELEGRAM_NOTIFICATIONS, TELEGRAM_ALERTS_CHAT_ID, TELEGRAM_BOT_API, TELEGRAM_STATS_CHAT_ID } from "../../config"; import { FetchJob } from "../../jobs/fetch/FetchJob"; -import { AppConfig } from "../../models/AppConfig"; import { IJob } from "../../models/IJob"; +import { InternalPairDeviationCheckerModuleConfig, PairDeviationCheckerModuleConfig, parsePairDeviationCheckerModuleConfig } from "./models/PairDeviationCheckerModuleConfig"; import { Module } from "../../models/Module"; import { OutcomeType } from "../../models/Outcome"; +import { PairDeviationReport } from "./models/PairDeviationReport"; +import { createRequestsFromPairs, PairDeviationDataRequest } from "./models/PairDeviationDataRequest"; import { createSafeAppConfigString } from "../../services/AppConfigUtils"; -import logger from "../../services/LoggerService"; import { debouncedInterval } from "../../services/TimerUtils"; -import { InternalPairDeviationCheckerModuleConfig, PairDeviationCheckerModuleConfig, parsePairDeviationCheckerModuleConfig } from "./models/PairDeviationCheckerModuleConfig"; -import { createRequestsFromPairs, PairDeviationDataRequest } from "./models/PairDeviationDataRequest"; -import { PairDeviationReport } from "./models/PairDeviationReport"; import { fetchLatestPrice, fetchLatestTimestamp } from "./services/FetchLastUpdateService"; -import { shouldPricePairUpdate } from "./services/PairDeviationService"; import { notifyTelegram } from "./services/TelegramNotificationService"; +import { prettySeconds } from "./utils"; +import { shouldPricePairUpdate } from "./services/PairDeviationService"; export class PairDeviationCheckerModule extends Module { static type = "PairDeviationCheckerModule"; @@ -100,8 +101,7 @@ export class PairDeviationCheckerModule extends Module { } this.prices.set(dataRequest.internalId, new Big(executeOutcome.answer)); - - logger.info(`[${this.id}] ${dataRequest.extraInfo.pair} has been recently updated`); + logger.info(`[${this.id}] ${dataRequest.extraInfo.pair} has been recently updated (${prettySeconds(Math.floor(timestampDiff / 1000), true)} ago)`); return { pair: dataRequest, diff --git a/src/modules/pushPair/PushPairModule.ts b/src/modules/pushPair/PushPairModule.ts index 96ca1b2..cb08b3b 100644 --- a/src/modules/pushPair/PushPairModule.ts +++ b/src/modules/pushPair/PushPairModule.ts @@ -1,3 +1,4 @@ +import Big from "big.js"; import EvmNetwork from "../../networks/evm/EvmNetwork"; import logger from "../../services/LoggerService"; import { AppConfig } from "../../models/AppConfig"; @@ -10,7 +11,7 @@ import { createPairIfNeeded } from "./services/PushPairCreationService"; import { createSafeAppConfigString } from "../../services/AppConfigUtils"; import { fetchEvmLastUpdate, fetchLatestPrice, fetchNearLastUpdate } from './services/FetchLastUpdateService'; import { parsePushPairConfig, PushPairConfig, PushPairInternalConfig } from "./models/PushPairConfig"; -import Big from "big.js"; +import { prettySeconds } from "../pairChecker/utils"; export class PushPairModule extends Module { static type = "PushPairModule"; @@ -47,9 +48,12 @@ export class PushPairModule extends Module { private async processPairs() { try { + // TODO: lastUpdates = fetchLastUpdate() should return an array of pair last updates + // TODO: lastUpdate = oldest pair last update const lastUpdate = await this.fetchLastUpdate(); // Fetch elapsed time (in milliseconds) since last pair(s) update const timeSinceUpdate = Date.now() - lastUpdate; + logger.debug(`[${this.id}] Oldest pair update: ${prettySeconds(Math.floor(timeSinceUpdate / 1000))} ago`); let remainingInterval; if (timeSinceUpdate < this.internalConfig.interval) { @@ -78,6 +82,7 @@ export class PushPairModule extends Module { } // When the prices don't deviate too much we don't need to update the price pair + // TODO: shouldPricePairUpdate should use `lastUpdates[index]` if (!shouldPricePairUpdate(unresolvedRequest, lastUpdate, new Big(outcome.answer), this.prices.get(unresolvedRequest.internalId))) { logger.debug(`[${this.id}] ${unresolvedRequest.internalId} Price ${outcome.answer} doesn't deviate ${unresolvedRequest.extraInfo.deviationPercentage}% from ${this.prices.get(unresolvedRequest.internalId)}`); remainingInterval = this.internalConfig.interval; diff --git a/src/modules/pushPair/services/FetchLastUpdateService.ts b/src/modules/pushPair/services/FetchLastUpdateService.ts index c741c18..bd681c1 100644 --- a/src/modules/pushPair/services/FetchLastUpdateService.ts +++ b/src/modules/pushPair/services/FetchLastUpdateService.ts @@ -1,16 +1,17 @@ +import Big from 'big.js'; import EvmNetwork from '../../../networks/evm/EvmNetwork'; import FluxPriceFeed from '../FluxPriceFeed.json'; import FluxPriceFeedFactory from '../FluxPriceFeedFactory.json'; import FluxPriceFeedFactory2 from '../FluxPriceFeedFactory2.json'; import { NearNetwork } from "../../../networks/near/NearNetwork"; +import { Network } from '../../../models/Network'; +import { PushPairDataRequest } from '../models/PushPairDataRequest'; import { PushPairInternalConfig } from "../models/PushPairConfig"; import { computeFactoryPairId } from "./utils"; -import { PushPairDataRequest } from '../models/PushPairDataRequest'; -import { Network } from '../../../models/Network'; -import Big from 'big.js'; export async function fetchEvmLastUpdate(config: PushPairInternalConfig, network: EvmNetwork) { let timestamp; + if (config.pairsType === 'single') { timestamp = await network.view({ method: 'latestTimestamp', @@ -20,26 +21,41 @@ export async function fetchEvmLastUpdate(config: PushPairInternalConfig, network abi: FluxPriceFeed.abi, }); } else if (config.pairsType === 'factory') { - // Contract returns [answer, updatedAt, statusCode] - timestamp = (await network.view({ - method: 'valueFor', - address: config.contractAddress, - amount: '0', - params: { - id: computeFactoryPairId(config.pairs[0].pair, config.pairs[0].decimals) - }, - abi: FluxPriceFeedFactory.abi, - }))[1]; + let pairTimestamps: Big[] = []; + for await (let pair of config.pairs) { + // Contract returns [answer, updatedAt, statusCode] + const pairTimestamp = (await network.view({ + method: 'valueFor', + address: config.contractAddress, + amount: '0', + params: { + id: computeFactoryPairId(pair.pair, pair.decimals) + }, + abi: FluxPriceFeedFactory.abi, + }))[1]; + + pairTimestamps.push(pairTimestamp); + } + + timestamp = pairTimestamps.reduce((prev, next) => prev.gt(next) ? next : prev); } else { // factory2 - timestamp = (await network.view({ - method: 'valueFor', - address: config.contractAddress, - amount: '0', - params: { - id: computeFactoryPairId(config.pairs[0].pair, config.pairs[0].decimals, network.getWalletPublicAddress()), - }, - abi: FluxPriceFeedFactory2.abi, - }))[1]; + let pairTimestamps: Big[] = []; + for await (let pair of config.pairs) { + // Contract returns [answer, updatedAt, statusCode] + const pairTimestamp = (await network.view({ + method: 'valueFor', + address: config.contractAddress, + amount: '0', + params: { + id: computeFactoryPairId(pair.pair, pair.decimals, network.getWalletPublicAddress()), + }, + abi: FluxPriceFeedFactory2.abi, + }))[1]; + + pairTimestamps.push(pairTimestamp); + } + + timestamp = pairTimestamps.reduce((prev, next) => prev.gt(next) ? next : prev); } // Convert contract timestamp to milliseconds @@ -47,18 +63,25 @@ export async function fetchEvmLastUpdate(config: PushPairInternalConfig, network } export async function fetchNearLastUpdate(config: PushPairInternalConfig, network: NearNetwork) { - const entry = await network.view({ - method: 'get_entry', - address: config.contractAddress, - amount: '0', - params: { - provider: network.internalConfig?.account.accountId, - pair: config.pairs[0].pair, - }, - }); + let pairTimestamps: number[] = []; + for await (let pair of config.pairs) { + const entry = await network.view({ + method: 'get_entry', + address: config.contractAddress, + amount: '0', + params: { + provider: network.internalConfig?.account.accountId, + pair: config.pairs[0].pair, + }, + }); - // Convert contract timestamp to milliseconds - return Math.floor(entry.last_update / 1000000); + // Convert contract timestamp to milliseconds + pairTimestamps.push(Math.floor(entry.last_update / 1000000)); + } + + const timestamp = pairTimestamps.reduce((prev, next) => prev > next ? next : prev); + + return timestamp; } export async function fetchLatestPrice(config: PushPairInternalConfig, pair: PushPairDataRequest, network: Network): Promise {