From fd040bafabdd12f5932f9e3b70862c9c6b2b2730 Mon Sep 17 00:00:00 2001 From: mtyszczak <mateusz.tyszczak@gmail.com> Date: Fri, 3 Jan 2025 12:56:16 +0100 Subject: [PATCH] Add feed price collector --- package.json | 2 +- pnpm-lock.yaml | 10 ++--- src/bot.ts | 2 +- .../classifiers/feed-price-classifier.ts | 14 +++++++ src/chain-observers/classifiers/index.ts | 1 + .../jsonrpc/feed-price-collector.ts | 42 +++++++++++++++++++ .../factories/jsonrpc/factory-data.ts | 6 ++- src/wax/index.ts | 21 ++++++++-- 8 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 src/chain-observers/classifiers/feed-price-classifier.ts create mode 100644 src/chain-observers/collectors/jsonrpc/feed-price-collector.ts diff --git a/package.json b/package.json index 0818c8c..bd61d05 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ }, "dependencies": { "@hiveio/beekeeper": "1.27.6-rc4", - "@hiveio/wax": "1.27.6-rc6" + "@hiveio/wax": "1.27.6-rc6-stable.241219120852" }, "repository": { "type": "git", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a155b73..ebf8bd0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: 1.27.6-rc4 version: 1.27.6-rc4 '@hiveio/wax': - specifier: 1.27.6-rc6 - version: 1.27.6-rc6 + specifier: 1.27.6-rc6-stable.241219120852 + version: 1.27.6-rc6-stable.241219120852 devDependencies: '@eslint/compat': specifier: ^1.2.2 @@ -165,8 +165,8 @@ packages: resolution: {integrity: sha1-mj3k3qAgTdIrc6IxzC5VOprhWZs=, tarball: https://gitlab.syncad.com/api/v4/projects/198/packages/npm/@hiveio/beekeeper/-/@hiveio/beekeeper-1.27.6-rc4.tgz} engines: {node: '>= 18'} - '@hiveio/wax@1.27.6-rc6': - resolution: {integrity: sha1-zIoajnS/Ct89scl0F/b1jtpk6hs=, tarball: https://gitlab.syncad.com/api/v4/projects/419/packages/npm/@hiveio/wax/-/@hiveio/wax-1.27.6-rc6.tgz} + '@hiveio/wax@1.27.6-rc6-stable.241219120852': + resolution: {integrity: sha1-4uoDcargMqnEY0eoYJCcyCcbHeM=, tarball: https://gitlab.syncad.com/api/v4/projects/419/packages/npm/@hiveio/wax/-/@hiveio/wax-1.27.6-rc6-stable.241219120852.tgz} engines: {node: '>= 18'} '@humanfs/core@0.19.1': @@ -2646,7 +2646,7 @@ snapshots: '@hiveio/beekeeper@1.27.6-rc4': {} - '@hiveio/wax@1.27.6-rc6': + '@hiveio/wax@1.27.6-rc6-stable.241219120852': dependencies: '@hiveio/beekeeper': 1.27.6-rc4 class-transformer: 0.5.1 diff --git a/src/bot.ts b/src/bot.ts index db4aef0..650af8b 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -45,7 +45,7 @@ export const DEFAULT_BLOCK_INTERVAL_TIMEOUT_MS = 2000; export class WorkerBee implements IWorkerBee { public readonly configuration: IStartConfiguration; - public chain?: TWaxExtended<typeof WaxExtendTypes>; + public chain?: TWaxExtended<WaxExtendTypes>; private wallet?: IBeekeeperUnlockedWallet; diff --git a/src/chain-observers/classifiers/feed-price-classifier.ts b/src/chain-observers/classifiers/feed-price-classifier.ts new file mode 100644 index 0000000..45f40a5 --- /dev/null +++ b/src/chain-observers/classifiers/feed-price-classifier.ts @@ -0,0 +1,14 @@ +import { price } from "@hiveio/wax"; +import { CollectorClassifierBase } from "./collector-classifier-base"; + +export interface IFeedPriceData { + currentMedianHistory: price; + marketMedianHistory: price; + currentMinHistory: price; + currentMaxHistory: price; + priceHistory: Iterable<price>; +} + +export class FeedPriceClassifier extends CollectorClassifierBase { + public type!: IFeedPriceData; +} diff --git a/src/chain-observers/classifiers/index.ts b/src/chain-observers/classifiers/index.ts index d70374d..4e4d01a 100644 --- a/src/chain-observers/classifiers/index.ts +++ b/src/chain-observers/classifiers/index.ts @@ -5,3 +5,4 @@ export { AccountClassifier } from "./account-classifier"; export { RcAccountClassifier } from "./rc-account-classifier"; export { ImpactedAccountClassifier } from "./impacted-account-classifier"; export { OperationClassifier } from "./operation-classifier"; +export { FeedPriceClassifier } from "./feed-price-classifier"; diff --git a/src/chain-observers/collectors/jsonrpc/feed-price-collector.ts b/src/chain-observers/collectors/jsonrpc/feed-price-collector.ts new file mode 100644 index 0000000..022f5a2 --- /dev/null +++ b/src/chain-observers/collectors/jsonrpc/feed-price-collector.ts @@ -0,0 +1,42 @@ +import { DynamicGlobalPropertiesClassifier } from "../../classifiers"; +import { IFeedPriceData } from "../../classifiers/feed-price-classifier"; +import { DataEvaluationContext } from "../../factories/data-evaluation-context"; +import { CollectorBase, TAvailableClassifiers } from "../collector-base"; + +const isDivisibleByInRange = (by: number, start: number, end: number) => { + // Normalize start to the next multiple of *by* + const firstMultiple = Math.ceil(start / by) * by; + + return firstMultiple <= end; +}; + +export class FeedPriceCollector extends CollectorBase { + private cachedFeedHistoryData: IFeedPriceData | undefined; + + private previouslyCheckedBlockNumber = 0; + + public async fetchData(data: DataEvaluationContext) { + const { headBlockNumber } = await data.get(DynamicGlobalPropertiesClassifier); + + // Update feed price history every hour (HIVE_FEED_INTERVAL_BLOCKS) or when there is no cached data + if ( this.cachedFeedHistoryData === undefined + || isDivisibleByInRange(Number.parseInt(this.worker.chain!.config["HIVE_FEED_INTERVAL_BLOCKS"]), headBlockNumber, this.previouslyCheckedBlockNumber) + ) { + const feedHistoryData = await this.worker.chain!.api.database_api.get_feed_history({}); + + this.cachedFeedHistoryData = { + currentMedianHistory: feedHistoryData.current_median_history, + marketMedianHistory: feedHistoryData.market_median_history, + currentMinHistory: feedHistoryData.current_min_history, + currentMaxHistory: feedHistoryData.current_max_history, + priceHistory: feedHistoryData.price_history + }; + } + + this.previouslyCheckedBlockNumber = headBlockNumber; + + return { + FeedPriceClassifier: this.cachedFeedHistoryData + } satisfies Partial<TAvailableClassifiers>; + }; +} diff --git a/src/chain-observers/factories/jsonrpc/factory-data.ts b/src/chain-observers/factories/jsonrpc/factory-data.ts index 9d6ddde..e70deac 100644 --- a/src/chain-observers/factories/jsonrpc/factory-data.ts +++ b/src/chain-observers/factories/jsonrpc/factory-data.ts @@ -1,7 +1,7 @@ import type { WorkerBee } from "../../../bot"; import { AccountClassifier, BlockClassifier, BlockHeaderClassifier, - DynamicGlobalPropertiesClassifier, ImpactedAccountClassifier, OperationClassifier, RcAccountClassifier + DynamicGlobalPropertiesClassifier, FeedPriceClassifier, ImpactedAccountClassifier, OperationClassifier, RcAccountClassifier } from "../../classifiers"; import { IEvaluationContextClass } from "../../classifiers/collector-classifier-base"; import { CollectorBase } from "../../collectors/collector-base"; @@ -11,6 +11,7 @@ import { OperationCollector } from "../../collectors/common/operation-collector" import { AccountCollector } from "../../collectors/jsonrpc/account-collector"; import { BlockCollector } from "../../collectors/jsonrpc/block-collector"; import { DynamicGlobalPropertiesCollector } from "../../collectors/jsonrpc/dynamic-global-properties-collector"; +import { FeedPriceCollector } from "../../collectors/jsonrpc/feed-price-collector"; import { RcAccountCollector } from "../../collectors/jsonrpc/rc-account-collector"; export const JsonRpcFactoryData: (worker: WorkerBee) => Array<[IEvaluationContextClass, CollectorBase]> = (worker: WorkerBee) => ([ @@ -20,5 +21,6 @@ export const JsonRpcFactoryData: (worker: WorkerBee) => Array<[IEvaluationContex [AccountClassifier, new AccountCollector(worker)], [RcAccountClassifier, new RcAccountCollector(worker)], [ImpactedAccountClassifier, new ImpactedAccountCollector(worker)], - [OperationClassifier, new OperationCollector(worker)] + [OperationClassifier, new OperationCollector(worker)], + [FeedPriceClassifier, new FeedPriceCollector(worker)] ]); diff --git a/src/wax/index.ts b/src/wax/index.ts index c04a740..93558f9 100644 --- a/src/wax/index.ts +++ b/src/wax/index.ts @@ -1,11 +1,24 @@ -import { createHiveChain, IHiveChainInterface, IWaxOptionsChain, TWaxExtended } from "@hiveio/wax"; +import { createHiveChain, IHiveChainInterface, IWaxOptionsChain, price, TWaxExtended } from "@hiveio/wax"; -export const WaxExtendTypes = {}; +export type WaxExtendTypes = { + database_api: { + get_feed_history: { + params: {}, + result: { + current_median_history: price; + market_median_history: price; + current_min_history: price; + current_max_history: price; + price_history: price[]; + } + } + } +}; -export const getWax = async(explicitHiveChain?: IHiveChainInterface, options?: Partial<IWaxOptionsChain>): Promise<TWaxExtended<typeof WaxExtendTypes>> => { +export const getWax = async(explicitHiveChain?: IHiveChainInterface, options?: Partial<IWaxOptionsChain>): Promise<TWaxExtended<WaxExtendTypes>> => { if(explicitHiveChain === undefined) explicitHiveChain = await createHiveChain(options); - return explicitHiveChain.extend(WaxExtendTypes); + return explicitHiveChain.extend<WaxExtendTypes>(); }; -- GitLab