From d4a6ccdb36b84bdc02c8f52f78e8f086965aa5f0 Mon Sep 17 00:00:00 2001 From: mtyszczak <mateusz.tyszczak@gmail.com> Date: Wed, 8 Jan 2025 12:37:13 +0100 Subject: [PATCH] Add internal market filter and provider --- .../filters/internal-market-filter.ts | 34 +++++++ .../providers/feed-price-provider.ts | 2 +- .../providers/internal-market-provider.ts | 95 +++++++++++++++++++ src/queen.ts | 9 ++ 4 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 src/chain-observers/filters/internal-market-filter.ts create mode 100644 src/chain-observers/providers/internal-market-provider.ts diff --git a/src/chain-observers/filters/internal-market-filter.ts b/src/chain-observers/filters/internal-market-filter.ts new file mode 100644 index 0000000..8f2d1a9 --- /dev/null +++ b/src/chain-observers/filters/internal-market-filter.ts @@ -0,0 +1,34 @@ +import type { WorkerBee } from "../../bot"; +import { OperationClassifier } from "../classifiers"; +import type { TRegisterEvaluationContext } from "../classifiers/collector-classifier-base"; +import type { DataEvaluationContext } from "../factories/data-evaluation-context"; +import { FilterBase } from "./filter-base"; + +export class InternalMarketFilter extends FilterBase { + public constructor( + worker: WorkerBee + ) { + super(worker); + } + + public usedContexts(): Array<TRegisterEvaluationContext> { + return [ + OperationClassifier + ]; + } + + public async match(data: DataEvaluationContext): Promise<boolean> { + const { operationsPerType } = await data.get(OperationClassifier); + + for(const {} of (operationsPerType.limit_order_create2 ?? [])) + return true; + + for(const {} of (operationsPerType.limit_order_cancel ?? [])) + return true; + + for(const {} of (operationsPerType.limit_order_create ?? [])) + return true; + + return false; + } +} diff --git a/src/chain-observers/providers/feed-price-provider.ts b/src/chain-observers/providers/feed-price-provider.ts index 4e413c3..a927d75 100644 --- a/src/chain-observers/providers/feed-price-provider.ts +++ b/src/chain-observers/providers/feed-price-provider.ts @@ -1,5 +1,5 @@ import { price } from "@hiveio/wax"; -import { WorkerBeeIterable } from "src/types/iterator"; +import { WorkerBeeIterable } from "../../types/iterator"; import { FeedPriceClassifier } from "../classifiers"; import { TRegisterEvaluationContext } from "../classifiers/collector-classifier-base"; import { DataEvaluationContext } from "../factories/data-evaluation-context"; diff --git a/src/chain-observers/providers/internal-market-provider.ts b/src/chain-observers/providers/internal-market-provider.ts new file mode 100644 index 0000000..1d12c2a --- /dev/null +++ b/src/chain-observers/providers/internal-market-provider.ts @@ -0,0 +1,95 @@ +import { price, type asset } from "@hiveio/wax"; +import { WorkerBeeIterable } from "../../types/iterator"; +import { TRegisterEvaluationContext } from "../classifiers/collector-classifier-base"; +import { OperationClassifier, IOperationTransactionPair } from "../classifiers/operation-classifier"; +import { DataEvaluationContext } from "../factories/data-evaluation-context"; +import { ProviderBase } from "./provider-base"; + +export interface IInternalMarketOperationBase { + owner: string; + orderId: number; +} + +export interface IInternalMarketCancelOperation extends IInternalMarketOperationBase { + cancel: true; +} + +export interface IInternalMarketCreateOperation extends IInternalMarketOperationBase { + cancel: false; + amountToSell: asset; + filled: boolean; + exchangeRate: price; + expiration: Date; +} + +export type TInternalMarketOperation = IInternalMarketCancelOperation | IInternalMarketCreateOperation; + +export interface IInternalMarketProviderData { + internalMarketOperations: WorkerBeeIterable<IOperationTransactionPair<TInternalMarketOperation>>; +}; + +export class InternalMarketProvider extends ProviderBase { + public usedContexts(): Array<TRegisterEvaluationContext> { + return [ + OperationClassifier + ] + } + + public async provide(data: DataEvaluationContext): Promise<IInternalMarketProviderData> { + const operations = await data.get(OperationClassifier); + + const orderCreate = operations.operationsPerType["limit_order_create"]; + const orderCreate2 = operations.operationsPerType["limit_order_create2"]; + const orderCancel = operations.operationsPerType["limit_order_cancel"]; + + const internalMarketOperations: IOperationTransactionPair<TInternalMarketOperation>[] = []; + + if(orderCancel) + for(const op of orderCancel) + internalMarketOperations.push({ + operation: { + cancel: true, + owner: op.operation.owner, + orderId: op.operation.orderid + }, + transaction: op.transaction + }); + + if(orderCreate) + for(const op of orderCreate) + internalMarketOperations.push({ + operation: { + cancel: false, + owner: op.operation.owner, + orderId: op.operation.orderid, + amountToSell: op.operation.amount_to_sell!, + filled: op.operation.fill_or_kill, + exchangeRate: { + base: op.operation.amount_to_sell, + quote: op.operation.min_to_receive + }, + expiration: new Date(`${op.operation.expiration}Z`) + }, + transaction: op.transaction + }); + + if(orderCreate2) + for(const op of orderCreate2) + internalMarketOperations.push({ + operation: { + cancel: false, + owner: op.operation.owner, + orderId: op.operation.orderid, + amountToSell: op.operation.amount_to_sell!, + filled: op.operation.fill_or_kill, + exchangeRate: op.operation.exchange_rate!, + expiration: new Date(`${op.operation.expiration}Z`) + }, + transaction: op.transaction + }); + + return { + internalMarketOperations: new WorkerBeeIterable(internalMarketOperations) + }; + } +} diff --git a/src/queen.ts b/src/queen.ts index 9fb9337..7b1c8dc 100644 --- a/src/queen.ts +++ b/src/queen.ts @@ -14,6 +14,7 @@ import { FeedPriceNoChangeFilter } from "./chain-observers/filters/feed-price-no import type { FilterBase } from "./chain-observers/filters/filter-base"; import { FollowFilter } from "./chain-observers/filters/follow-filter"; import { ImpactedAccountFilter } from "./chain-observers/filters/impacted-account-filter"; +import { InternalMarketFilter } from "./chain-observers/filters/internal-market-filter"; import { BlockChangedFilter } from "./chain-observers/filters/new-block-filter"; import { PostFilter } from "./chain-observers/filters/post-filter"; import { PostMentionFilter } from "./chain-observers/filters/post-mention"; @@ -27,6 +28,7 @@ import { BlockHeaderProvider } from "./chain-observers/providers/block-header-pr import { BlockProvider } from "./chain-observers/providers/block-provider"; import { ExchangeTransferProvider } from "./chain-observers/providers/exchange-transfer-provider"; import { FeedPriceProvider } from "./chain-observers/providers/feed-price-provider"; +import { InternalMarketProvider } from "./chain-observers/providers/internal-market-provider"; import { MentionedAccountProvider } from "./chain-observers/providers/mention-provider"; import { ProviderBase } from "./chain-observers/providers/provider-base"; import { RcAccountProvider } from "./chain-observers/providers/rc-account-provider"; @@ -190,6 +192,13 @@ export class QueenBee<TPreviousSubscriberData extends object = {}> { return this; } + public onInternalMarketOperation(): QueenBee<TPreviousSubscriberData & Awaited<ReturnType<InternalMarketProvider["provide"]>>> { + this.operands.push(new InternalMarketFilter(this.worker)); + this.providers.push(new InternalMarketProvider()); + + return this; + } + public onBlock(): QueenBee<TPreviousSubscriberData & Awaited<ReturnType<BlockHeaderProvider["provide"]>>> { this.operands.push(new BlockChangedFilter(this.worker)); this.providers.push(new BlockHeaderProvider()); -- GitLab