diff --git a/packages/api/src/graphql/GraphqlSequencerModule.ts b/packages/api/src/graphql/GraphqlSequencerModule.ts index 5342e3702..2aaadf248 100644 --- a/packages/api/src/graphql/GraphqlSequencerModule.ts +++ b/packages/api/src/graphql/GraphqlSequencerModule.ts @@ -1,16 +1,19 @@ -import assert from "node:assert"; - +import { buildSchemaSync, NonEmptyArray } from "type-graphql"; import { Closeable, closeable, SequencerModule } from "@proto-kit/sequencer"; import { ChildContainerProvider, Configurable, + CombinedModuleContainerConfig, log, ModuleContainer, ModulesRecord, TypedClass, } from "@proto-kit/common"; +import { GraphQLSchema } from "graphql/type"; +import { stitchSchemas } from "@graphql-tools/stitch"; +import { createYoga } from "graphql-yoga"; +import Koa from "koa"; -import { GraphqlServer } from "./GraphqlServer"; import { GraphqlModule, ResolverFactoryGraphqlModule, @@ -21,11 +24,46 @@ export type GraphqlModulesRecord = ModulesRecord< TypedClass> >; +export interface GraphqlServerConfig { + host: string; + port: number; + graphiql: boolean; +} + +export type GraphqlSequencerModuleConfig< + GraphQLModules extends GraphqlModulesRecord, +> = CombinedModuleContainerConfig; + +type Server = ReturnType; + +function assertArrayIsNotEmpty( + array: readonly T[], + errorMessage: string +): asserts array is NonEmptyArray { + if (array.length === 0) { + throw new Error(errorMessage); + } +} + @closeable() export class GraphqlSequencerModule - extends ModuleContainer + extends ModuleContainer implements Configurable, SequencerModule, Closeable { + private readonly modules: TypedClass>[] = []; + + private readonly schemas: GraphQLSchema[] = []; + + private resolvers: NonEmptyArray | undefined; + + private server?: Server; + + private context: {} = {}; + + public get serverConfig(): GraphqlServerConfig { + return this.containerConfig; + } + public static from( definition: GraphQLModules ): TypedClass> { @@ -36,19 +74,28 @@ export class GraphqlSequencerModule }; } - private graphqlServer?: GraphqlServer; + public constructor(definition: GraphQLModules) { + super(definition); + } + + public setContext(newContext: {}) { + this.context = newContext; + } + + public registerResolvers(resolvers: NonEmptyArray) { + if (this.resolvers === undefined) { + this.resolvers = resolvers; + } else { + this.resolvers = [...this.resolvers, ...resolvers]; + } + } public create(childContainerProvider: ChildContainerProvider) { super.create(childContainerProvider); - - this.graphqlServer = this.container.resolve("GraphqlServer"); + this.container.register("GraphqlServer", { useValue: this }); } public async start(): Promise { - assert(this.graphqlServer !== undefined); - - this.graphqlServer.setContainer(this.container); - // eslint-disable-next-line guard-for-in for (const moduleName in this.definition) { const moduleClass = this.definition[moduleName]; @@ -65,9 +112,9 @@ export class GraphqlSequencerModule moduleName ) as ResolverFactoryGraphqlModule; // eslint-disable-next-line no-await-in-loop - this.graphqlServer.registerResolvers(await module.resolvers()); + this.registerResolvers(await module.resolvers()); } else { - this.graphqlServer.registerModule(moduleClass); + this.modules.push(moduleClass); if ( Object.prototype.isPrototypeOf.call( @@ -80,16 +127,91 @@ export class GraphqlSequencerModule const module = this.resolve( moduleName ) as SchemaGeneratingGraphqlModule; - this.graphqlServer.registerSchema(module.generateSchema()); + this.schemas.push(module.generateSchema()); } } } - await this.graphqlServer.startServer(); + await this.startServer(); + } + + // Server logic + + private async startServer() { + const { modules, container: dependencyContainer } = this; + + const resolvers = [...modules, ...(this.resolvers || [])]; + + assertArrayIsNotEmpty( + resolvers, + "At least one module has to be provided to GraphqlServer" + ); + + // Building schema + const resolverSchema = buildSchemaSync({ + resolvers, + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + container: { get: (cls) => dependencyContainer.resolve(cls) }, + validate: { + enableDebugMessages: true, + }, + }); + + // Instantiate all modules at startup + modules.forEach((module) => { + dependencyContainer.resolve(module); + }); + + const schema = [resolverSchema, ...this.schemas].reduce( + (schema1, schema2) => + stitchSchemas({ + subschemas: [{ schema: schema1 }, { schema: schema2 }], + }) + ); + + const app = new Koa(); + + const { graphiql, port, host } = this.serverConfig; + + const yoga = createYoga({ + schema, + graphiql, + context: this.context, + }); + + // Bind GraphQL Yoga to `/graphql` endpoint + app.use(async (ctx) => { + // Second parameter adds Koa's context into GraphQL Context + const response = await yoga.handleNodeRequest(ctx.req, ctx); + + // Set status code + ctx.status = response.status; + + // Set headers + response.headers.forEach((value, key) => { + ctx.append(key, value); + }); + + // Converts ReadableStream to a NodeJS Stream + ctx.body = response.body; + }); + + this.server = app.listen({ port, host }, () => { + log.info(`GraphQL Server listening on ${host}:${port}`); + }); } public async close() { - if (this.graphqlServer !== undefined) { - await this.graphqlServer.close(); + if (this.server !== undefined) { + const { server } = this; + + await new Promise((res) => { + server.close((error) => { + if (error !== undefined) { + log.error(error); + } + res(); + }); + }); } } } diff --git a/packages/cli/src/scripts/graphqlDocs/generateGqlDocs.ts b/packages/cli/src/scripts/graphqlDocs/generateGqlDocs.ts index 0ed012519..4b6d8734f 100644 --- a/packages/cli/src/scripts/graphqlDocs/generateGqlDocs.ts +++ b/packages/cli/src/scripts/graphqlDocs/generateGqlDocs.ts @@ -19,7 +19,7 @@ export default async function (args: { VanillaProtocolModules, VanillaRuntimeModules, } = await import("@proto-kit/library"); - const { GraphqlSequencerModule, GraphqlServer, VanillaGraphqlModules } = + const { GraphqlSequencerModule, VanillaGraphqlModules } = await import("@proto-kit/api"); const { Runtime } = await import("@proto-kit/module"); const { port } = args; @@ -30,7 +30,6 @@ export default async function (args: { Protocol: Protocol.from(VanillaProtocolModules.with({})), Sequencer: Sequencer.from( InMemorySequencerModules.with({ - GraphqlServer: GraphqlServer, Graphql: GraphqlSequencerModule.from(VanillaGraphqlModules.with({})), }) ), @@ -45,7 +44,7 @@ export default async function (args: { Sequencer: { Database: {}, TaskQueue: {}, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), Mempool: {}, BlockProducerModule: {}, SequencerStartupModule: {}, @@ -53,8 +52,14 @@ export default async function (args: { FeeStrategy: {}, BaseLayer: {}, BatchProducerModule: {}, - Graphql: VanillaGraphqlModules.defaultConfig(), - GraphqlServer: { port, host: "localhost", graphiql: true }, + Graphql: { + ...VanillaGraphqlModules.defaultConfig(), + containerConfig: { + port, + host: "localhost", + graphiql: true, + }, + }, }, }); diff --git a/packages/cli/src/utils/create-environment.ts b/packages/cli/src/utils/create-environment.ts index cdafadf58..f95eecb80 100644 --- a/packages/cli/src/utils/create-environment.ts +++ b/packages/cli/src/utils/create-environment.ts @@ -339,10 +339,10 @@ export function generateWorkerConfig(answers: WizardAnswers): string { const presetEnv = PRESET_ENV_NAMES[answers.preset]; const taskWorkerImports = answers.settlementEnabled ? "" - : " LocalTaskWorkerModule, VanillaTaskWorkerModules"; + : " WorkerModule, VanillaTaskWorkerModules"; const withoutSettlementTask = answers.settlementEnabled ? "" - : `LocalTaskWorkerModule: LocalTaskWorkerModule.from( + : `WorkerModule: WorkerModule.from( VanillaTaskWorkerModules.withoutSettlement() ), `; diff --git a/packages/common/src/config/ModuleContainer.ts b/packages/common/src/config/ModuleContainer.ts index 7424759c9..a7cf26927 100644 --- a/packages/common/src/config/ModuleContainer.ts +++ b/packages/common/src/config/ModuleContainer.ts @@ -98,6 +98,11 @@ export type ModulesConfig = { : never; }; +export type CombinedModuleContainerConfig< + Modules extends ModulesRecord, + ContainerConfig = NoConfig, +> = ModulesConfig & { containerConfig?: ContainerConfig }; + /** * This type make any config partial (i.e. optional) up to the first level * So { Module: { a: { b: string } } } @@ -139,9 +144,18 @@ export interface ModuleContainerLike { /** * Reusable module container facilitating registration, resolution * configuration, decoration and validation of modules + * + * @typeParam Modules - The record of child module classes. + * @typeParam ContainerConfig - Optional config type for keys that belong to the + * container itself (not forwarded to child modules). Defaults to NoConfig. */ -export class ModuleContainer - extends ConfigurableModule> +export class ModuleContainer< + Modules extends ModulesRecord, + ContainerConfig = NoConfig, +> + extends ConfigurableModule< + CombinedModuleContainerConfig + > implements ModuleContainerLike { /** @@ -159,6 +173,14 @@ export class ModuleContainer super(); } + /** + * Returns the container's own configuration. + */ + public get containerConfig(): ContainerConfig { + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + return this.config?.containerConfig as ContainerConfig; + } + /** * @returns list of module names */ @@ -296,25 +318,34 @@ export class ModuleContainer * before the first resolution. * @param config */ - public configure(config: ModulesConfig) { + public configure( + config: CombinedModuleContainerConfig + ) { this.config = config; } - public configurePartial(config: RecursivePartial>) { - this.config = merge< - ModulesConfig | NoConfig, - RecursivePartial> - >(this.currentConfig ?? {}, config); + public configurePartial( + config: RecursivePartial< + CombinedModuleContainerConfig + > + ) { + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + this.config = merge( + this.currentConfig ?? {}, + config + ) as CombinedModuleContainerConfig; } public get config() { return super.config; } - public set config(config: ModulesConfig) { + public set config( + config: CombinedModuleContainerConfig + ) { super.config = merge< - ModulesConfig | NoConfig, - ModulesConfig + CombinedModuleContainerConfig | NoConfig, + CombinedModuleContainerConfig >(this.currentConfig ?? {}, config); } diff --git a/packages/common/src/events/EventEmitterProxy.ts b/packages/common/src/events/EventEmitterProxy.ts index cb7e46b4c..b38a96f1b 100644 --- a/packages/common/src/events/EventEmitterProxy.ts +++ b/packages/common/src/events/EventEmitterProxy.ts @@ -42,7 +42,9 @@ export type FlattenedContainerEvents = export class EventEmitterProxy< Modules extends ModulesRecord, > extends EventEmitter>> { - public constructor(private readonly container: ModuleContainer) { + public constructor( + private readonly container: ModuleContainer + ) { super(); container.moduleNames.forEach((moduleName) => { if (container.isValidModuleName(container.definition, moduleName)) { diff --git a/packages/deployment/src/queue/BullQueue.ts b/packages/deployment/src/queue/BullQueue.ts index 2a4f4e640..2f459b81b 100644 --- a/packages/deployment/src/queue/BullQueue.ts +++ b/packages/deployment/src/queue/BullQueue.ts @@ -116,6 +116,6 @@ export class BullQueue public async close() { await this.closeQueues(); - // Closing of active workers is handled by the LocalTaskWorkerModule + // Closing of active workers is handled by the WorkerModule } } diff --git a/packages/indexer/src/api/GeneratedResolverFactoryGraphqlModule.ts b/packages/indexer/src/api/GeneratedResolverFactoryGraphqlModule.ts index 9c631c48b..fd31b1814 100644 --- a/packages/indexer/src/api/GeneratedResolverFactoryGraphqlModule.ts +++ b/packages/indexer/src/api/GeneratedResolverFactoryGraphqlModule.ts @@ -1,5 +1,6 @@ import { - GraphqlServer, + GraphqlModulesRecord, + GraphqlSequencerModule, ResolverFactoryGraphqlModule, graphqlModule, } from "@proto-kit/api"; @@ -97,7 +98,8 @@ export function ValidateTakeArg() { @graphqlModule() export class GeneratedResolverFactoryGraphqlModule extends ResolverFactoryGraphqlModule { public constructor( - @inject("GraphqlServer") public graphqlServer: GraphqlServer + @inject("GraphqlServer") + public graphqlServer: GraphqlSequencerModule ) { super(); } diff --git a/packages/indexer/test/GeneratedResolverFactoryGraphqlModule.test.ts b/packages/indexer/test/GeneratedResolverFactoryGraphqlModule.test.ts index 3ef0ffe06..b70d88c94 100644 --- a/packages/indexer/test/GeneratedResolverFactoryGraphqlModule.test.ts +++ b/packages/indexer/test/GeneratedResolverFactoryGraphqlModule.test.ts @@ -1,9 +1,5 @@ import "reflect-metadata"; -import { - GraphqlSequencerModule, - GraphqlServer, - graphqlModule, -} from "@proto-kit/api"; +import { GraphqlSequencerModule, graphqlModule } from "@proto-kit/api"; import { log } from "@proto-kit/common"; import { jest } from "@jest/globals"; @@ -30,20 +26,19 @@ class MockedGeneratedResolverFactoryGraphqlModule extends GeneratedResolverFacto describe("GeneratedResolverFactoryGraphqlModule", () => { const indexer = Indexer.from({ - GraphqlServer: GraphqlServer, Graphql: GraphqlSequencerModule.from({ GeneratedResolverFactory: MockedGeneratedResolverFactoryGraphqlModule, }), }); indexer.configurePartial({ - GraphqlServer: { - port, - host: "0.0.0.0", - graphiql: true, - }, Graphql: { GeneratedResolverFactory: {}, + containerConfig: { + port, + host: "0.0.0.0", + graphiql: true, + }, }, }); @@ -136,6 +131,6 @@ describe("GeneratedResolverFactoryGraphqlModule", () => { }); afterAll(async () => { - await indexer.resolve("GraphqlServer").close(); + await indexer.resolve("Graphql").close(); }); }); diff --git a/packages/indexer/test/IndexBlockTask.test.ts b/packages/indexer/test/IndexBlockTask.test.ts index b5432e5a3..abdc583c0 100644 --- a/packages/indexer/test/IndexBlockTask.test.ts +++ b/packages/indexer/test/IndexBlockTask.test.ts @@ -3,7 +3,7 @@ import { BlockWithResult, InMemoryDatabase, LocalTaskQueue, - LocalTaskWorkerModule, + WorkerModule, TaskPayload, } from "@proto-kit/sequencer"; @@ -14,7 +14,7 @@ describe("IndexBlockTask", () => { const indexer = Indexer.from({ Database: InMemoryDatabase, TaskQueue: LocalTaskQueue, - LocalTaskWorkerModule: LocalTaskWorkerModule.from({ + WorkerModule: WorkerModule.from({ IndexBlockTask: IndexBlockTask, }), }); @@ -22,7 +22,7 @@ describe("IndexBlockTask", () => { indexer.configurePartial({ Database: {}, TaskQueue: {}, - LocalTaskWorkerModule: { + WorkerModule: { IndexBlockTask: {}, }, }); @@ -30,8 +30,8 @@ describe("IndexBlockTask", () => { it("should listen to block indexing tasks", async () => { await indexer.start(); const taskQueue = indexer.resolve("TaskQueue"); - const localTaskWorker = indexer.resolve("LocalTaskWorkerModule"); - const indexBlockTask = localTaskWorker.resolve("IndexBlockTask"); + const workerModule = indexer.resolve("WorkerModule"); + const indexBlockTask = workerModule.resolve("IndexBlockTask"); const queue = await taskQueue.getQueue(indexBlockTask.name); const block = BlockWithResult.createEmpty(); diff --git a/packages/indexer/test/IndexerNotifier.test.ts b/packages/indexer/test/IndexerNotifier.test.ts index ddd37b498..3a740b64f 100644 --- a/packages/indexer/test/IndexerNotifier.test.ts +++ b/packages/indexer/test/IndexerNotifier.test.ts @@ -90,7 +90,7 @@ function createAppChain() { BlockTrigger: {}, Mempool: {}, BlockProducerModule: {}, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), BaseLayer: {}, BatchProducerModule: {}, TaskQueue: { diff --git a/packages/library/src/sequencer/InMemorySequencerModules.ts b/packages/library/src/sequencer/InMemorySequencerModules.ts index f880b33d2..4a61cb4cd 100644 --- a/packages/library/src/sequencer/InMemorySequencerModules.ts +++ b/packages/library/src/sequencer/InMemorySequencerModules.ts @@ -2,7 +2,7 @@ import { BatchProducerModule, InMemoryDatabase, LocalTaskQueue, - LocalTaskWorkerModule, + WorkerModule, ManualBlockTrigger, NoopBaseLayer, PrivateMempool, @@ -18,9 +18,7 @@ import { TypedClass } from "@proto-kit/common"; export type InMemorySequencerModulesRecord = { Database: typeof InMemoryDatabase; Mempool: typeof PrivateMempool; - LocalTaskWorkerModule: TypedClass< - LocalTaskWorkerModule - >; + WorkerModule: TypedClass>; BaseLayer: typeof NoopBaseLayer; BatchProducerModule: typeof BatchProducerModule; BlockProducerModule: typeof BlockProducerModule; @@ -37,7 +35,7 @@ export class InMemorySequencerModules { return { Database: InMemoryDatabase, Mempool: PrivateMempool, - LocalTaskWorkerModule: LocalTaskWorkerModule.from({ + WorkerModule: WorkerModule.from({ ...VanillaTaskWorkerModules.withoutSettlement(), }), FeeStrategy: ConstantFeeStrategy, diff --git a/packages/library/src/sequencer/SimpleSequencerModules.ts b/packages/library/src/sequencer/SimpleSequencerModules.ts index 2d50200e4..835ab1ea1 100644 --- a/packages/library/src/sequencer/SimpleSequencerModules.ts +++ b/packages/library/src/sequencer/SimpleSequencerModules.ts @@ -1,6 +1,6 @@ import { BatchProducerModule, - LocalTaskWorkerModule, + WorkerModule, PrivateMempool, SequencerModulesRecord, BlockProducerModule, @@ -37,8 +37,8 @@ export type AdditionalSequencerModules = SequencerModulesRecord & MinimumAdditionalSequencerModules; export type SimpleSequencerWorkerModulesRecord = { - LocalTaskWorkerModule: TypedClass< - LocalTaskWorkerModule> + WorkerModule: TypedClass< + WorkerModule> >; TaskQueue: TypedClass; }; @@ -49,9 +49,7 @@ export class SimpleSequencerModules { SequencerModules extends SequencerModulesRecord, >(queue: TypedClass, additionalModules: SequencerModules) { return { - LocalTaskWorkerModule: LocalTaskWorkerModule.from( - VanillaTaskWorkerModules.allTasks() - ), + WorkerModule: WorkerModule.from(VanillaTaskWorkerModules.allTasks()), TaskQueue: queue, ...additionalModules, } satisfies SimpleSequencerWorkerModulesRecord; @@ -96,9 +94,7 @@ export class SimpleSequencerModules { public static defaultConfig() { return { - BlockProducerModule: { - allowEmptyBlock: true, - }, + BlockProducerModule: {}, Mempool: {}, BatchProducerModule: {}, @@ -108,9 +104,9 @@ export class SimpleSequencerModules { public static defaultWorkerConfig() { return { - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), } satisfies ModulesConfig< - Pick + Pick >; } } diff --git a/packages/persistance/src/PrismaRedisDatabase.ts b/packages/persistance/src/PrismaRedisDatabase.ts index 87ef9af46..522f5708c 100644 --- a/packages/persistance/src/PrismaRedisDatabase.ts +++ b/packages/persistance/src/PrismaRedisDatabase.ts @@ -5,8 +5,13 @@ import { Database, closeable, Tracer, + Prunable, } from "@proto-kit/sequencer"; -import { ChildContainerProvider, dependencyFactory } from "@proto-kit/common"; +import { + ChildContainerProvider, + dependencyFactory, + log, +} from "@proto-kit/common"; import { PrismaClient } from "@prisma/client"; import { RedisClientType } from "redis"; import { inject } from "tsyringe"; @@ -27,6 +32,7 @@ import { PrismaLinkedLeafStore } from "./services/prisma/PrismaLinkedLeafStore"; export interface PrismaRedisCombinedConfig { prisma: PrismaDatabaseConfig; redis: RedisConnectionConfig; + pruneOnStartup?: boolean; } @sequencerModule() @@ -34,7 +40,7 @@ export interface PrismaRedisCombinedConfig { @dependencyFactory() export class PrismaRedisDatabase extends SequencerModule - implements PrismaConnection, RedisConnection, Database + implements PrismaConnection, RedisConnection, Database, Prunable { public prisma: PrismaDatabaseConnection; @@ -99,6 +105,11 @@ export class PrismaRedisDatabase this.redis.config = this.config.redis; await this.redis.start(); + + if (this.config?.pruneOnStartup ?? false) { + log.info("Pruning database"); + await this.pruneDatabase(); + } } public async close() { diff --git a/packages/persistance/test-integration/PrismaBlockProduction.test.ts b/packages/persistance/test-integration/PrismaBlockProduction.test.ts index 5589b2275..bd91bbb0d 100644 --- a/packages/persistance/test-integration/PrismaBlockProduction.test.ts +++ b/packages/persistance/test-integration/PrismaBlockProduction.test.ts @@ -34,6 +34,9 @@ describe("Prisma block production", () => { log: [{ level: "query", emit: "event" }], }, redis: redisConfig, + databasePruneModule: { + pruneOnStartup: true, + }, } as never ); }); diff --git a/packages/persistance/test-integration/SequencerRestart.test.ts b/packages/persistance/test-integration/SequencerRestart.test.ts index 2864424b9..8980d8512 100644 --- a/packages/persistance/test-integration/SequencerRestart.test.ts +++ b/packages/persistance/test-integration/SequencerRestart.test.ts @@ -29,11 +29,6 @@ describe("sequencer restart", () => { Signer: { signer: sender, }, - Sequencer: { - DatabasePruneModule: { - pruneOnStartup: false, - }, - }, }); await appChain.start(false, container.createChildContainer()); diff --git a/packages/persistance/test-integration/utils.ts b/packages/persistance/test-integration/utils.ts index e62050794..231d72cf1 100644 --- a/packages/persistance/test-integration/utils.ts +++ b/packages/persistance/test-integration/utils.ts @@ -25,7 +25,7 @@ import { import { BatchProducerModule, LocalTaskQueue, - LocalTaskWorkerModule, + WorkerModule, ManualBlockTrigger, NoopBaseLayer, PrivateMempool, @@ -33,7 +33,6 @@ import { BlockProducerModule, VanillaTaskWorkerModules, SequencerStartupModule, - DatabasePruneModule, } from "@proto-kit/sequencer"; import { Bool, PrivateKey, PublicKey, Struct } from "o1js"; @@ -92,7 +91,8 @@ export class MintableBalances extends Balances { export function createPrismaAppchain( prismaConnection: PrismaDatabaseConfig["connection"], - redisConnection: RedisConnectionConfig + redisConnection: RedisConnectionConfig, + pruneOnStartup = false ) { const appChain = ClientAppChain.from({ Protocol: Protocol.from(VanillaProtocolModules.mandatoryModules({})), @@ -100,11 +100,10 @@ export function createPrismaAppchain( Balances: MintableBalances, }), Sequencer: Sequencer.from({ - DatabasePruneModule, Database: PrismaRedisDatabase, Mempool: PrivateMempool, - LocalTaskWorkerModule: LocalTaskWorkerModule.from( + WorkerModule: WorkerModule.from( VanillaTaskWorkerModules.withoutSettlement() ), BaseLayer: NoopBaseLayer, @@ -139,20 +138,18 @@ export function createPrismaAppchain( connection: prismaConnection, }, redis: redisConnection, + pruneOnStartup, }, BlockTrigger: {}, Mempool: {}, BatchProducerModule: {}, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), BaseLayer: {}, BlockProducerModule: {}, TaskQueue: { simulatedDuration: 0, }, SequencerStartupModule: {}, - DatabasePruneModule: { - pruneOnStartup: true, - }, }, Signer: { signer: PrivateKey.random(), diff --git a/packages/processor/src/api/ResolverFactoryGraphqlModule.ts b/packages/processor/src/api/ResolverFactoryGraphqlModule.ts index a110b0be6..3ac532073 100644 --- a/packages/processor/src/api/ResolverFactoryGraphqlModule.ts +++ b/packages/processor/src/api/ResolverFactoryGraphqlModule.ts @@ -1,5 +1,6 @@ import { - GraphqlServer, + GraphqlModulesRecord, + GraphqlSequencerModule, ResolverFactoryGraphqlModule as BaseResolverFactoryGraphqlModule, graphqlModule, } from "@proto-kit/api"; @@ -61,7 +62,9 @@ export class ResolverFactoryGraphqlModule< public database: PrismaDatabaseConnection | undefined; - public constructor(public graphqlServer: GraphqlServer) { + public constructor( + public graphqlServer: GraphqlSequencerModule + ) { super(); } diff --git a/packages/sdk/src/testing/TestingAppChain.ts b/packages/sdk/src/testing/TestingAppChain.ts index 3487a4175..6d6c2c234 100644 --- a/packages/sdk/src/testing/TestingAppChain.ts +++ b/packages/sdk/src/testing/TestingAppChain.ts @@ -67,7 +67,7 @@ export class TestingAppChain< BlockTrigger: {}, Mempool: {}, BatchProducerModule: {}, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), BaseLayer: {}, BlockProducerModule: {}, SequencerStartupModule: {}, diff --git a/packages/sequencer/src/index.ts b/packages/sequencer/src/index.ts index 7da10194e..b9a2b133a 100644 --- a/packages/sequencer/src/index.ts +++ b/packages/sequencer/src/index.ts @@ -20,7 +20,7 @@ export * from "./worker/queue/LocalTaskQueue"; export * from "./worker/queue/ListenerList"; export * from "./worker/queue/AbstractTaskQueue"; export * from "./worker/worker/FlowTaskWorker"; -export * from "./worker/worker/LocalTaskWorkerModule"; +export * from "./worker/worker/WorkerModule"; export * from "./worker/worker/TaskWorkerModule"; export * from "./worker/worker/WorkerReadyModule"; export * from "./protocol/baselayer/BaseLayer"; @@ -64,6 +64,7 @@ export * from "./protocol/production/tracing/BlockTracingService"; export * from "./protocol/production/tracing/BatchTracingService"; export * from "./protocol/production/tracing/StateTransitionTracingService"; export * from "./protocol/production/tracing/TransactionTracingService"; +export * from "./sequencer/SequencerCoreModule"; export * from "./sequencer/SequencerStartupModule"; export * from "./sequencer/SettlementStartupModule"; export * from "./sequencer/builder/StartableModule"; @@ -84,7 +85,7 @@ export * from "./storage/inmemory/InMemoryMessageStorage"; export * from "./storage/inmemory/InMemoryTransactionStorage"; export * from "./storage/StorageDependencyFactory"; export * from "./storage/Database"; -export * from "./storage/DatabasePruneModule"; +export * from "./storage/Prunable"; export * from "./helpers/query/QueryTransportModule"; export * from "./helpers/query/QueryBuilderFactory"; export * from "./helpers/query/NetworkStateQuery"; diff --git a/packages/sequencer/src/mempool/Mempool.ts b/packages/sequencer/src/mempool/Mempool.ts index 5770df70b..37e779a10 100644 --- a/packages/sequencer/src/mempool/Mempool.ts +++ b/packages/sequencer/src/mempool/Mempool.ts @@ -25,4 +25,6 @@ export interface Mempool< removeTxs: (included: string[], dropped: string[]) => Promise; length: () => Promise; + + getTargetBlockSize: () => number; } diff --git a/packages/sequencer/src/mempool/private/PrivateMempool.ts b/packages/sequencer/src/mempool/private/PrivateMempool.ts index 277a6957d..e3c2f6d70 100644 --- a/packages/sequencer/src/mempool/private/PrivateMempool.ts +++ b/packages/sequencer/src/mempool/private/PrivateMempool.ts @@ -17,6 +17,7 @@ import { DefaultMempoolSorting } from "../sorting/DefaultMempoolSorting"; type PrivateMempoolConfig = { type?: "hybrid" | "private" | "based"; + targetBlockSize?: number; }; @sequencerModule() @@ -46,6 +47,10 @@ export class PrivateMempool return this.config.type ?? "hybrid"; } + public getTargetBlockSize(): number { + return this.config.targetBlockSize ?? 20; + } + public async length(): Promise { const numUserTxs = await this.transactionStorage.countPendingUserTransactions(); diff --git a/packages/sequencer/src/protocol/production/sequencing/BlockBuilder.ts b/packages/sequencer/src/protocol/production/sequencing/BlockBuilder.ts index 6ebe0b43c..b1a684cfd 100644 --- a/packages/sequencer/src/protocol/production/sequencing/BlockBuilder.ts +++ b/packages/sequencer/src/protocol/production/sequencing/BlockBuilder.ts @@ -62,8 +62,7 @@ export class BlockBuilder { public async buildBlock( asyncStateService: CachedStateService, networkState: NetworkState, - state: BlockTrackers, - maximumBlockSize: number + state: BlockTrackers ): Promise<{ blockState: BlockTrackers; executionResults: TransactionExecutionResultStatus[]; @@ -74,7 +73,8 @@ export class BlockBuilder { const networkStateHash = networkState.hash(); - const ordering = new Ordering(this.mempool, maximumBlockSize); + const targetBlockSize = this.mempool.getTargetBlockSize(); + const ordering = new Ordering(this.mempool, targetBlockSize); let tx: PendingTransaction | undefined; // eslint-disable-next-line no-await-in-loop,no-cond-assign diff --git a/packages/sequencer/src/protocol/production/sequencing/BlockProducerModule.ts b/packages/sequencer/src/protocol/production/sequencing/BlockProducerModule.ts index 278de217a..b90059d9f 100644 --- a/packages/sequencer/src/protocol/production/sequencing/BlockProducerModule.ts +++ b/packages/sequencer/src/protocol/production/sequencing/BlockProducerModule.ts @@ -32,8 +32,7 @@ import { BlockProductionService } from "./BlockProductionService"; import { BlockResultService } from "./BlockResultService"; export interface BlockConfig { - allowEmptyBlock?: boolean; - maximumBlockSize?: number; + skipEmptyBlocks?: boolean; } @sequencerModule() @@ -61,12 +60,8 @@ export class BlockProducerModule extends SequencerModule { super(); } - private allowEmptyBlock() { - return this.config.allowEmptyBlock ?? true; - } - - private maximumBlockSize() { - return this.config.maximumBlockSize ?? 20; + private skipEmptyBlocks() { + return this.config.skipEmptyBlocks ?? false; } private prettyPrintBlockContents(block: Block) { @@ -143,7 +138,7 @@ export class BlockProducerModule extends SequencerModule { const block = await this.produceBlock(); if (block === undefined) { - if (!this.allowEmptyBlock()) { + if (this.skipEmptyBlocks()) { log.info("No transactions in mempool, skipping production"); } else { log.error("Something wrong happened, skipping block"); @@ -192,15 +187,14 @@ export class BlockProducerModule extends SequencerModule { const blockResult = await this.productionService.createBlock( this.unprovenStateService, metadata, - this.allowEmptyBlock(), - this.maximumBlockSize() + this.skipEmptyBlocks() ); if (blockResult !== undefined) { const { block, stateChanges, orderingMetadata } = blockResult; // Skip production if no transactions are available for now - if (block.transactions.length === 0 && !this.allowEmptyBlock()) { + if (block.transactions.length === 0 && this.skipEmptyBlocks()) { return undefined; } diff --git a/packages/sequencer/src/protocol/production/sequencing/BlockProductionService.ts b/packages/sequencer/src/protocol/production/sequencing/BlockProductionService.ts index 95ad398a4..ceaba6a79 100644 --- a/packages/sequencer/src/protocol/production/sequencing/BlockProductionService.ts +++ b/packages/sequencer/src/protocol/production/sequencing/BlockProductionService.ts @@ -102,8 +102,7 @@ export class BlockProductionService { public async createBlock( asyncStateService: AsyncStateService, lastBlockWithResult: BlockWithResult, - allowEmptyBlocks: boolean, - maximumBlockSize: number + skipEmptyBlocks: boolean ): Promise< | { block: Block; @@ -151,14 +150,13 @@ export class BlockProductionService { } = await this.blockBuilder.buildBlock( stateService, networkState, - blockState, - maximumBlockSize + blockState ); const previousBlockHash = lastResult.blockHash === 0n ? undefined : Field(lastResult.blockHash); - if (executionResults.length === 0 && !allowEmptyBlocks) { + if (executionResults.length === 0 && skipEmptyBlocks) { log.info( "After sequencing, block has no sequenceable transactions left, skipping block" ); diff --git a/packages/sequencer/src/protocol/production/sequencing/Ordering.ts b/packages/sequencer/src/protocol/production/sequencing/Ordering.ts index 9cc8132ae..b27a3aaec 100644 --- a/packages/sequencer/src/protocol/production/sequencing/Ordering.ts +++ b/packages/sequencer/src/protocol/production/sequencing/Ordering.ts @@ -77,7 +77,7 @@ export class PathResolution { export class Ordering { public constructor( private readonly mempool: Mempool, - private sizeLimit: number + private targetBlockSize: number ) {} mandatoryTransactionsCompleted = false; @@ -140,7 +140,7 @@ export class Ordering { } private space() { - return this.sizeLimit - this.ordered; + return this.targetBlockSize - this.ordered; } private mandoQueue: PendingTransaction[] = []; diff --git a/packages/sequencer/src/sequencer/SequencerCoreModule.ts b/packages/sequencer/src/sequencer/SequencerCoreModule.ts new file mode 100644 index 000000000..6ac7802aa --- /dev/null +++ b/packages/sequencer/src/sequencer/SequencerCoreModule.ts @@ -0,0 +1,132 @@ +import { + DependencyDeclaration, + DependencyRecord, + dependencyFactory, + NoConfig, +} from "@proto-kit/common"; +import { inject } from "tsyringe"; + +import { + BlockConfig, + BlockProducerModule, +} from "../protocol/production/sequencing/BlockProducerModule"; +import { BatchProducerModule } from "../protocol/production/BatchProducerModule"; + +import { SequencerModule, sequencerModule } from "./builder/SequencerModule"; +import { closeable } from "./builder/Closeable"; +import { SequencerStartupModule } from "./SequencerStartupModule"; + +export interface LocalSequencerCoreDependencies extends DependencyRecord { + SequencerStartupModule: DependencyDeclaration< + SequencerStartupModule, + LocalSequencerCoreModule + >; + BlockProducerModule: DependencyDeclaration< + BlockProducerModule, + LocalSequencerCoreModule + >; +} + +export interface SequencerCoreDependencies extends DependencyRecord { + SequencerStartupModule: DependencyDeclaration< + SequencerStartupModule, + SequencerCoreModule + >; + BlockProducerModule: DependencyDeclaration< + BlockProducerModule, + SequencerCoreModule + >; + BatchProducerModule: DependencyDeclaration< + BatchProducerModule, + SequencerCoreModule + >; +} + +export interface LocalSequencerCoreConfig { + SequencerStartupModule: NoConfig; + BlockProducerModule: BlockConfig; +} + +export interface SequencerCoreConfig extends LocalSequencerCoreConfig { + BatchProducerModule: NoConfig; +} + +@sequencerModule() +@closeable() +@dependencyFactory() +export class LocalSequencerCoreModule extends SequencerModule { + public constructor( + @inject("SequencerStartupModule") + private readonly sequencerStartupModule: SequencerStartupModule, + @inject("BlockProducerModule") + private readonly blockProducerModule: BlockProducerModule + ) { + super(); + } + + public static dependencies(): LocalSequencerCoreDependencies { + return { + SequencerStartupModule: { + useClass: SequencerStartupModule, + }, + BlockProducerModule: { + useClass: BlockProducerModule, + }, + }; + } + + public create() { + this.sequencerStartupModule.config = this.config.SequencerStartupModule; + this.blockProducerModule.config = this.config.BlockProducerModule; + } + + public async start(): Promise { + await this.sequencerStartupModule.start(); + await this.blockProducerModule.start(); + } + + public async close(): Promise { + await this.sequencerStartupModule.close(); + } +} + +@sequencerModule() +@dependencyFactory() +export class SequencerCoreModule extends SequencerModule { + public constructor( + @inject("SequencerStartupModule") + private readonly sequencerStartupModule: SequencerStartupModule, + @inject("BlockProducerModule") + private readonly blockProducerModule: BlockProducerModule, + @inject("BatchProducerModule") + private readonly batchProducerModule: BatchProducerModule + ) { + super(); + } + + public static dependencies(): SequencerCoreDependencies { + return { + SequencerStartupModule: { + useClass: SequencerStartupModule, + }, + BlockProducerModule: { + useClass: BlockProducerModule, + }, + BatchProducerModule: { + useClass: BatchProducerModule, + }, + }; + } + + public create() { + this.sequencerStartupModule.config = this.config.SequencerStartupModule; + this.blockProducerModule.config = this.config.BlockProducerModule; + this.batchProducerModule.config = this.config.BatchProducerModule; + } + + public async start(): Promise { + await this.sequencerStartupModule.start(); + await this.blockProducerModule.start(); + await this.batchProducerModule.start(); + } +} diff --git a/packages/sequencer/src/storage/Database.ts b/packages/sequencer/src/storage/Database.ts index 60d4c9b17..b0138ef79 100644 --- a/packages/sequencer/src/storage/Database.ts +++ b/packages/sequencer/src/storage/Database.ts @@ -1,12 +1,5 @@ import { Closeable } from "../sequencer/builder/Closeable"; export interface Database extends Closeable { - /** - * Prunes all data from the database connection. - * Note: This function should only be called immediately at startup, - * everything else will lead to unexpected behaviour and errors - */ - pruneDatabase(): Promise; - executeInTransaction(f: () => Promise): Promise; } diff --git a/packages/sequencer/src/storage/DatabasePruneModule.ts b/packages/sequencer/src/storage/DatabasePruneModule.ts deleted file mode 100644 index e2b3e5689..000000000 --- a/packages/sequencer/src/storage/DatabasePruneModule.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { inject } from "tsyringe"; -import { noop, log } from "@proto-kit/common"; - -import { - SequencerModule, - sequencerModule, -} from "../sequencer/builder/SequencerModule"; - -import { Database } from "./Database"; - -export type DatabasePruneConfig = { - pruneOnStartup?: boolean; -}; - -@sequencerModule() -export class DatabasePruneModule extends SequencerModule { - public constructor(@inject("Database") private readonly database: Database) { - super(); - } - - public async start() { - try { - if (this.config?.pruneOnStartup ?? false) { - log.info("Pruning database"); - await this.database.pruneDatabase(); - } - } catch (e) { - noop(); - } - } -} diff --git a/packages/sequencer/src/storage/Prunable.ts b/packages/sequencer/src/storage/Prunable.ts new file mode 100644 index 000000000..db2c9700a --- /dev/null +++ b/packages/sequencer/src/storage/Prunable.ts @@ -0,0 +1,8 @@ +export interface Prunable { + /** + * Prunes all data from the database connection. + * Note: This function should only be called immediately at startup, + * everything else will lead to unexpected behaviour and errors + */ + pruneDatabase(): Promise; +} diff --git a/packages/sequencer/src/worker/worker/LocalTaskWorkerModule.ts b/packages/sequencer/src/worker/worker/WorkerModule.ts similarity index 92% rename from packages/sequencer/src/worker/worker/LocalTaskWorkerModule.ts rename to packages/sequencer/src/worker/worker/WorkerModule.ts index 85fa05663..2cdefc3a0 100644 --- a/packages/sequencer/src/worker/worker/LocalTaskWorkerModule.ts +++ b/packages/sequencer/src/worker/worker/WorkerModule.ts @@ -44,7 +44,7 @@ export type TaskWorkerModulesRecord = ModulesRecord< TypedClass> >; -type LocalTaskWorkerModuleEvents = { ready: [boolean] }; +type WorkerModuleEvents = { ready: [boolean] }; /** * This module spins up a worker in the current local node instance. @@ -54,15 +54,13 @@ type LocalTaskWorkerModuleEvents = { ready: [boolean] }; */ @sequencerModule() @closeable() -export class LocalTaskWorkerModule +export class WorkerModule extends ModuleContainer - implements - SequencerModule, - EventEmittingContainer + implements SequencerModule, EventEmittingContainer { public static presets: Presets = {}; - public containerEvents = new EventEmitter(); + public containerEvents = new EventEmitter(); private worker?: FlowTaskWorker< InstanceType[StringKeyOf]>[] @@ -70,8 +68,8 @@ export class LocalTaskWorkerModule public static from( modules: Tasks - ): TypedClass> { - return class ScopedTaskWorkerModule extends LocalTaskWorkerModule { + ): TypedClass> { + return class ScopedWorkerModule extends WorkerModule { public constructor() { super(modules); } diff --git a/packages/sequencer/src/worker/worker/WorkerReadyModule.ts b/packages/sequencer/src/worker/worker/WorkerReadyModule.ts index 1f7a82a9b..01a986830 100644 --- a/packages/sequencer/src/worker/worker/WorkerReadyModule.ts +++ b/packages/sequencer/src/worker/worker/WorkerReadyModule.ts @@ -1,6 +1,6 @@ import { inject, injectable } from "tsyringe"; -import { LocalTaskWorkerModule } from "./LocalTaskWorkerModule"; +import { WorkerModule } from "./WorkerModule"; /** * Module to safely wait for the finish of the worker startup @@ -9,16 +9,14 @@ import { LocalTaskWorkerModule } from "./LocalTaskWorkerModule"; @injectable() export class WorkerReadyModule { public constructor( - @inject("LocalTaskWorkerModule", { isOptional: true }) - private readonly localTaskWorkerModule: - | LocalTaskWorkerModule - | undefined + @inject("WorkerModule", { isOptional: true }) + private readonly workerModule: WorkerModule | undefined ) {} // eslint-disable-next-line consistent-return public async waitForReady() { - if (this.localTaskWorkerModule !== undefined) { - const module = this.localTaskWorkerModule; + if (this.workerModule !== undefined) { + const module = this.workerModule; return await new Promise((res, rej) => { module.containerEvents.on("ready", (ready) => { if (ready) { diff --git a/packages/sequencer/test-integration/benchmarks/tps.test.ts b/packages/sequencer/test-integration/benchmarks/tps.test.ts index 68e2dd5a0..27c24b3bb 100644 --- a/packages/sequencer/test-integration/benchmarks/tps.test.ts +++ b/packages/sequencer/test-integration/benchmarks/tps.test.ts @@ -25,7 +25,6 @@ import { afterEach } from "@jest/globals"; import { BlockProducerModule, ConsoleTracer, - DatabasePruneModule, ManualBlockTrigger, Sequencer, } from "../../src"; @@ -65,7 +64,6 @@ export async function createAppChain() { ), Protocol: Protocol.from(VanillaProtocolModules.with({})), Sequencer: Sequencer.from({ - DatabasePruneModule, Database: PrismaRedisDatabase, Mempool: PrivateMempool, BlockProducerModule: BlockProducerModule, @@ -86,9 +84,6 @@ export async function createAppChain() { ...VanillaProtocolModules.defaultConfig(), }, Sequencer: { - DatabasePruneModule: { - pruneOnStartup: true, - }, Database: { redis: { host: "localhost", @@ -99,12 +94,13 @@ export async function createAppChain() { connection: "postgresql://admin:password@localhost:5432/protokit?schema=public", }, + pruneOnStartup: true, }, - BlockProducerModule: { - maximumBlockSize: 100, - }, + BlockProducerModule: {}, BlockTrigger: {}, - Mempool: {}, + Mempool: { + targetBlockSize: 100, + }, }, Signer: { signer: PrivateKey.random(), diff --git a/packages/sequencer/test-integration/workers/WorkerModules.ts b/packages/sequencer/test-integration/workers/WorkerModules.ts index e1d640aa3..e2b280655 100644 --- a/packages/sequencer/test-integration/workers/WorkerModules.ts +++ b/packages/sequencer/test-integration/workers/WorkerModules.ts @@ -1,6 +1,6 @@ -import { LocalTaskWorkerModule, TaskQueue, TypedClass } from "../../src"; +import { WorkerModule, TaskQueue, TypedClass } from "../../src"; export interface MinimumWorkerModules { TaskQueue: TypedClass; - LocalTaskWorkerModule: TypedClass>; + WorkerModule: TypedClass>; } diff --git a/packages/sequencer/test-integration/workers/worker.ts b/packages/sequencer/test-integration/workers/worker.ts index c9210b74b..f8b903aed 100644 --- a/packages/sequencer/test-integration/workers/worker.ts +++ b/packages/sequencer/test-integration/workers/worker.ts @@ -6,7 +6,7 @@ import { log, sleep } from "@proto-kit/common"; import { AppChain, - LocalTaskWorkerModule, + WorkerModule, Sequencer, VanillaTaskWorkerModules, } from "../../src"; @@ -25,7 +25,7 @@ async function main() { const sequencerClass = Sequencer.from({ TaskQueue: BullQueue, - LocalTaskWorkerModule: LocalTaskWorkerModule.from( + WorkerModule: WorkerModule.from( VanillaTaskWorkerModules.withoutSettlement() ), } satisfies MinimumWorkerModules); @@ -40,7 +40,7 @@ async function main() { ...runtimeProtocolConfig, Sequencer: { TaskQueue: BullConfig, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), }, }); @@ -56,7 +56,7 @@ async function main() { const ready = await new Promise((res) => { app .resolve("Sequencer") - .resolve("LocalTaskWorkerModule") + .resolve("WorkerModule") .containerEvents.on("ready", res); }); diff --git a/packages/sequencer/test-integration/workers/workers-proven.test.ts b/packages/sequencer/test-integration/workers/workers-proven.test.ts index 047a92913..4df7e74a4 100644 --- a/packages/sequencer/test-integration/workers/workers-proven.test.ts +++ b/packages/sequencer/test-integration/workers/workers-proven.test.ts @@ -91,11 +91,11 @@ describe("worker-proven", () => { Sequencer: { Database: {}, BlockTrigger: {}, - Mempool: {}, - BatchProducerModule: {}, - BlockProducerModule: { - maximumBlockSize: 5, + Mempool: { + targetBlockSize: 5, }, + BatchProducerModule: {}, + BlockProducerModule: {}, // BaseLayer: {}, TaskQueue: BullConfig, FeeStrategy: {}, diff --git a/packages/sequencer/test-proven/Proven.test.ts b/packages/sequencer/test-proven/Proven.test.ts index 14e41f9dd..b2f7fd16b 100644 --- a/packages/sequencer/test-proven/Proven.test.ts +++ b/packages/sequencer/test-proven/Proven.test.ts @@ -89,12 +89,12 @@ describe("Proven", () => { Sequencer: { Database: {}, BlockTrigger: {}, - Mempool: {}, - BatchProducerModule: {}, - BlockProducerModule: { - maximumBlockSize: 5, + Mempool: { + targetBlockSize: 5, }, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + BatchProducerModule: {}, + BlockProducerModule: {}, + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), TaskQueue: {}, FeeStrategy: {}, SequencerStartupModule: {}, diff --git a/packages/sequencer/test-proven/settlement-worker.ts b/packages/sequencer/test-proven/settlement-worker.ts index b4d53ff8d..3d27bc1ee 100644 --- a/packages/sequencer/test-proven/settlement-worker.ts +++ b/packages/sequencer/test-proven/settlement-worker.ts @@ -17,7 +17,7 @@ import { } from "../test/settlement/Settlement"; import { AppChain, - LocalTaskWorkerModule, + WorkerModule, Sequencer, VanillaTaskWorkerModules, } from "../src"; @@ -36,9 +36,7 @@ async function main() { const sequencerClass = Sequencer.from({ TaskQueue: BullQueue, - LocalTaskWorkerModule: LocalTaskWorkerModule.from( - VanillaTaskWorkerModules.allTasks() - ), + WorkerModule: WorkerModule.from(VanillaTaskWorkerModules.allTasks()), } satisfies MinimumWorkerModules); const app = AppChain.from({ @@ -52,7 +50,7 @@ async function main() { Protocol: protocolModulesConfig, Sequencer: { TaskQueue: BullConfig, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), }, }); diff --git a/packages/sequencer/test/TestingSequencer.ts b/packages/sequencer/test/TestingSequencer.ts index cb42747e5..99e6cdb9f 100644 --- a/packages/sequencer/test/TestingSequencer.ts +++ b/packages/sequencer/test/TestingSequencer.ts @@ -4,7 +4,7 @@ import { BatchProducerModule, InMemoryDatabase, LocalTaskQueue, - LocalTaskWorkerModule, + WorkerModule, ManualBlockTrigger, NoopBaseLayer, PrivateMempool, @@ -19,7 +19,7 @@ import { ConstantFeeStrategy } from "../src/protocol/baselayer/fees/ConstantFeeS export type DefaultTestingSequencerModules = { Database: typeof InMemoryDatabase; Mempool: typeof PrivateMempool; - LocalTaskWorkerModule: TypedClass>; + WorkerModule: TypedClass>; BaseLayer: typeof NoopBaseLayer; BatchProducerModule: typeof BatchProducerModule; BlockProducerModule: typeof BlockProducerModule; @@ -36,7 +36,7 @@ export function testingSequencerModules< modules: AdditionalModules, additionalTaskWorkerModules?: AdditionalTaskWorkerModules ) { - const taskWorkerModule = LocalTaskWorkerModule.from({ + const taskWorkerModule = WorkerModule.from({ ...VanillaTaskWorkerModules.withoutSettlement(), ...additionalTaskWorkerModules, }); @@ -45,7 +45,7 @@ export function testingSequencerModules< Database: InMemoryDatabase, Mempool: PrivateMempool, BaseLayer: NoopBaseLayer, - LocalTaskWorkerModule: taskWorkerModule, + WorkerModule: taskWorkerModule, BatchProducerModule, BlockProducerModule, BlockTrigger: ManualBlockTrigger, @@ -58,7 +58,7 @@ export function testingSequencerModules< ...defaultModules, ...modules, // We need to make sure that the taskworkermodule is initialized last - LocalTaskWorkerModule: defaultModules.LocalTaskWorkerModule, + WorkerModule: defaultModules.WorkerModule, SequencerStartupModule: defaultModules.SequencerStartupModule, } satisfies SequencerModulesRecord; } diff --git a/packages/sequencer/test/integration/Block-order.test.ts b/packages/sequencer/test/integration/Block-order.test.ts index e65aa9cd8..945ec444b 100644 --- a/packages/sequencer/test/integration/Block-order.test.ts +++ b/packages/sequencer/test/integration/Block-order.test.ts @@ -103,7 +103,7 @@ describe.each([["InMemory", InMemoryDatabase]])( FeeStrategy: {}, BatchProducerModule: {}, BlockProducerModule: {}, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), BaseLayer: {}, TaskQueue: {}, SequencerStartupModule: {}, @@ -250,7 +250,7 @@ describe.each([["InMemory", InMemoryDatabase]])( it("transactions are returned in right order in multiple distinct blocks - hardest", async () => { expect.assertions(18); - sequencer.resolve("BlockProducerModule").config.maximumBlockSize = 3; + sequencer.resolve("Mempool").config.targetBlockSize = 3; const txStorage = sequencer.resolve("TransactionStorage"); const getTxsSpy = jest.spyOn(txStorage, "getPendingUserTransactions"); diff --git a/packages/sequencer/test/integration/BlockProduction-test.ts b/packages/sequencer/test/integration/BlockProduction-test.ts index 8e2764a42..836d2cabb 100644 --- a/packages/sequencer/test/integration/BlockProduction-test.ts +++ b/packages/sequencer/test/integration/BlockProduction-test.ts @@ -31,10 +31,8 @@ import { Sequencer, SequencerModule, VanillaTaskWorkerModules, - DatabasePruneModule, AsyncLinkedLeafStore, AppChain, - BlockProducerModule, DatabaseDependencyFactory, } from "../../src"; import { @@ -125,7 +123,6 @@ export function testBlockProduction< }); const sequencerClass = Sequencer.from({ - DatabasePruneModule, ...testingSequencerModules({}), Database: database, }); @@ -145,15 +142,12 @@ export function testBlockProduction< app.configure({ Sequencer: { - DatabasePruneModule: { - pruneOnStartup: true, - }, Database: databaseConfig, BlockTrigger: {}, Mempool: {}, BatchProducerModule: {}, BlockProducerModule: {}, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), BaseLayer: {}, TaskQueue: {}, FeeStrategy: {}, @@ -697,10 +691,9 @@ export function testBlockProduction< async (numBlocks) => { log.setLevel("INFO"); - (sequencer.resolve("BlockProducerModule") as BlockProducerModule).config = - { - maximumBlockSize: 5, - }; + sequencer.resolve("Mempool").config = { + targetBlockSize: 5, + }; const privateKey = PrivateKey.random(); diff --git a/packages/sequencer/test/integration/BlockProductionSize.test.ts b/packages/sequencer/test/integration/BlockProductionSize.test.ts index 67d6d7ca6..4f6c4cce1 100644 --- a/packages/sequencer/test/integration/BlockProductionSize.test.ts +++ b/packages/sequencer/test/integration/BlockProductionSize.test.ts @@ -70,12 +70,12 @@ describe("block limit", () => { Sequencer: { Database: {}, BlockTrigger: {}, - Mempool: {}, - BatchProducerModule: {}, - BlockProducerModule: { - maximumBlockSize: maxBlockSize, + Mempool: { + targetBlockSize: maxBlockSize, }, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + BatchProducerModule: {}, + BlockProducerModule: {}, + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), BaseLayer: {}, TaskQueue: {}, FeeStrategy: {}, diff --git a/packages/sequencer/test/integration/MempoolTxRemoved.test.ts b/packages/sequencer/test/integration/MempoolTxRemoved.test.ts index 02fae71f5..818dc4407 100644 --- a/packages/sequencer/test/integration/MempoolTxRemoved.test.ts +++ b/packages/sequencer/test/integration/MempoolTxRemoved.test.ts @@ -50,7 +50,7 @@ describe("mempool removal mechanism", () => { Mempool: {}, BatchProducerModule: {}, BlockProducerModule: {}, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), BaseLayer: {}, TaskQueue: {}, FeeStrategy: {}, diff --git a/packages/sequencer/test/integration/StorageIntegration.test.ts b/packages/sequencer/test/integration/StorageIntegration.test.ts index c4df190c6..8ccbad72a 100644 --- a/packages/sequencer/test/integration/StorageIntegration.test.ts +++ b/packages/sequencer/test/integration/StorageIntegration.test.ts @@ -95,7 +95,7 @@ describe.each([["InMemory", InMemoryDatabase]])( Mempool: {}, BatchProducerModule: {}, BlockProducerModule: {}, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), BaseLayer: {}, TaskQueue: {}, FeeStrategy: {}, diff --git a/packages/sequencer/test/production/tracing/StateTransitionTracingService.test.ts b/packages/sequencer/test/production/tracing/StateTransitionTracingService.test.ts index a670b41c6..8dd0e317b 100644 --- a/packages/sequencer/test/production/tracing/StateTransitionTracingService.test.ts +++ b/packages/sequencer/test/production/tracing/StateTransitionTracingService.test.ts @@ -75,7 +75,7 @@ async function applyBatchesToTree( // const SequencerC = Sequencer.from({ // modules: { // TaskQueue: LocalTaskQueue, -// LocalTaskWorkerModule: LocalTaskWorkerModule.from({ +// WorkerModule: WorkerModule.from({ // StateTransitionTask, // StateTransitionReductionTask, // }), @@ -103,7 +103,7 @@ async function applyBatchesToTree( // // const sequencer = new SequencerC(); // sequencer.configure({ -// LocalTaskWorkerModule: { +// WorkerModule: { // StateTransitionTask: {}, // StateTransitionReductionTask: {}, // }, diff --git a/packages/sequencer/test/protocol/production/sequencing/atomic-block-production.test.ts b/packages/sequencer/test/protocol/production/sequencing/atomic-block-production.test.ts index 79dccbcd4..63f68d5e4 100644 --- a/packages/sequencer/test/protocol/production/sequencing/atomic-block-production.test.ts +++ b/packages/sequencer/test/protocol/production/sequencing/atomic-block-production.test.ts @@ -53,7 +53,7 @@ describe("atomic block production", () => { Mempool: {}, BatchProducerModule: {}, BlockProducerModule: {}, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), BaseLayer: {}, TaskQueue: {}, FeeStrategy: {}, diff --git a/packages/sequencer/test/settlement/Settlement-only.ts b/packages/sequencer/test/settlement/Settlement-only.ts index c894bfbcf..621d2ebc7 100644 --- a/packages/sequencer/test/settlement/Settlement-only.ts +++ b/packages/sequencer/test/settlement/Settlement-only.ts @@ -115,7 +115,7 @@ export const settlementOnlyTestFn = ( BlockTrigger: {}, Mempool: {}, BatchProducerModule: {}, - LocalTaskWorkerModule: { + WorkerModule: { ...VanillaTaskWorkerModules.defaultConfig(), }, BaseLayer: baseLayerConfig, diff --git a/packages/sequencer/test/settlement/Settlement.ts b/packages/sequencer/test/settlement/Settlement.ts index 40adaf414..027ff7953 100644 --- a/packages/sequencer/test/settlement/Settlement.ts +++ b/packages/sequencer/test/settlement/Settlement.ts @@ -58,7 +58,7 @@ import { Sequencer, InMemoryMinaSigner, CircuitAnalysisModule, - LocalTaskWorkerModule, + WorkerModule, InMemoryDatabase, BatchProducerModule, BlockProducerModule, @@ -170,7 +170,7 @@ export const settlementTestFn = ( MinaBaseLayer.prototype["isSignedSettlement"] = () => settlementType === "signed"; - const taskWorkerModule = LocalTaskWorkerModule.from( + const taskWorkerModule = WorkerModule.from( VanillaTaskWorkerModules.allTasks() ); @@ -189,7 +189,7 @@ export const settlementTestFn = ( ...(bullQueueConfig !== undefined ? {} : { - LocalTaskWorkerModule: taskWorkerModule, + WorkerModule: taskWorkerModule, }), SequencerStartupModule, }); @@ -215,7 +215,7 @@ export const settlementTestFn = ( BlockTrigger: {}, Mempool: {}, BatchProducerModule: {}, - LocalTaskWorkerModule: { + WorkerModule: { ...VanillaTaskWorkerModules.defaultConfig(), }, BaseLayer: baseLayerConfig, diff --git a/packages/stack/src/presets/modules/index.ts b/packages/stack/src/presets/modules/index.ts index 68f3bb86f..0a8403bca 100644 --- a/packages/stack/src/presets/modules/index.ts +++ b/packages/stack/src/presets/modules/index.ts @@ -1,7 +1,6 @@ import { VanillaGraphqlModules, GraphqlSequencerModule, - GraphqlServer, OpenTelemetryServer, } from "@proto-kit/api"; import { @@ -10,13 +9,12 @@ import { TimedBlockTrigger, BlockProducerModule, SequencerStartupModule, - LocalTaskWorkerModule, + WorkerModule, VanillaTaskWorkerModules, MinaBaseLayer, ConstantFeeStrategy, BatchProducerModule, SettlementModule, - DatabasePruneModule, InMemoryDatabase, LocalTaskQueue, AppChainModulesRecord, @@ -71,7 +69,6 @@ import { export class DefaultModules { static api() { return { - GraphqlServer, Graphql: GraphqlSequencerModule.from(VanillaGraphqlModules.with({})), } satisfies SequencerModulesRecord; } @@ -115,13 +112,12 @@ export class DefaultModules { return { Database: PrismaRedisDatabase, TaskQueue: BullQueue, - TaskWorker: LocalTaskWorkerModule.from({ + TaskWorker: WorkerModule.from({ IndexBlockTask, IndexPendingTxTask, IndexBatchTask, IndexSettlementTask, }), - GraphqlServer, Graphql: GraphqlSequencerModule.from({ GeneratedResolverFactory: GeneratedResolverFactoryGraphqlModule, }), @@ -133,7 +129,6 @@ export class DefaultModules { handlers: HandlersRecord ) { return { - GraphqlServer, GraphqlSequencerModule: GraphqlSequencerModule.from({ ResolverFactory: ResolverFactoryGraphqlModule.from(resolvers), }), @@ -152,13 +147,12 @@ export class DefaultModules { static prismaRedisDatabase() { return { Database: PrismaRedisDatabase, - DatabasePruneModule, } satisfies SequencerModulesRecord; } static localWorker(options?: { settlementEnabled?: boolean }) { return { - LocalTaskWorkerModule: LocalTaskWorkerModule.from( + WorkerModule: WorkerModule.from( options?.settlementEnabled === true ? VanillaTaskWorkerModules.allTasks() : VanillaTaskWorkerModules.withoutSettlement() @@ -176,9 +170,7 @@ export class DefaultModules { static remoteWorker() { return { TaskQueue: BullQueue, - LocalTaskWorkerModule: LocalTaskWorkerModule.from( - VanillaTaskWorkerModules.allTasks() - ), + WorkerModule: WorkerModule.from(VanillaTaskWorkerModules.allTasks()), } satisfies SequencerModulesRecord; } @@ -195,9 +187,7 @@ export class DefaultModules { ...DefaultModules.settlement(), Mempool: PrivateMempool, TaskQueue: LocalTaskQueue, - LocalTaskWorker: LocalTaskWorkerModule.from( - VanillaTaskWorkerModules.allTasks() - ), + WorkerModule: WorkerModule.from(VanillaTaskWorkerModules.allTasks()), SequencerStartupModule, BridgingModule: BridgingModule, } satisfies SequencerModulesRecord; @@ -208,12 +198,15 @@ export class DefaultConfigs { preset?: Environment; overrides?: Partial; }) { + const serverConfig = DefaultConfigs.graphqlServer({ + preset: options?.preset, + overrides: options?.overrides, + }); return { - Graphql: VanillaGraphqlModules.defaultConfig(), - ...DefaultConfigs.graphqlServer({ - preset: options?.preset, - overrides: options?.overrides, - }), + Graphql: { + ...VanillaGraphqlModules.defaultConfig(), + ...serverConfig.GraphqlServer, + }, }; } @@ -259,7 +252,7 @@ export class DefaultConfigs { BlockProducerModule: {}, BlockTrigger: blockTriggerConfig, SequencerStartupModule: {}, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), ...settlementConfig, }; } @@ -329,9 +322,9 @@ export class DefaultConfigs { IndexPendingTxTask: {}, IndexSettlementTask: {}, }, - ...graphqlServerConfig, Graphql: { GeneratedResolverFactory: {}, + ...graphqlServerConfig.GraphqlServer, }, }; } @@ -361,9 +354,9 @@ export class DefaultConfigs { Trigger: { interval: Number(config.blockInterval) / 5, }, - ...graphqlServerConfig, GraphqlSequencerModule: { ResolverFactory: {}, + ...graphqlServerConfig.GraphqlServer, }, }; } @@ -410,7 +403,7 @@ export class DefaultConfigs { }, FeeStrategy: {}, BatchProducerModule: {}, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), }; } @@ -434,9 +427,9 @@ export class DefaultConfigs { prisma: { connection: config.databaseUrl, }, - }, - DatabasePruneModule: { - pruneOnStartup: config.pruneOnStartup, + databasePruneModule: { + pruneOnStartup: config.pruneOnStartup, + }, }, }; } @@ -444,7 +437,7 @@ export class DefaultConfigs { static localWorker() { return { TaskQueue: {}, - LocalTaskWorkerModule: { + WorkerModule: { ...VanillaTaskWorkerModules.defaultConfig(), }, } satisfies ModulesConfig>; @@ -524,7 +517,7 @@ export class DefaultConfigs { return { ...taskQueueConfig, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), }; } diff --git a/packages/stack/src/scripts/graphql/server.ts b/packages/stack/src/scripts/graphql/server.ts index 2cdaf2604..7b22f4319 100644 --- a/packages/stack/src/scripts/graphql/server.ts +++ b/packages/stack/src/scripts/graphql/server.ts @@ -22,7 +22,7 @@ import { BatchProducerModule, InMemoryDatabase, LocalTaskQueue, - LocalTaskWorkerModule, + WorkerModule, NoopBaseLayer, PrivateMempool, Sequencer, @@ -34,7 +34,6 @@ import { import { BatchStorageResolver, GraphqlSequencerModule, - GraphqlServer, MempoolResolver, LinkedMerkleWitnessResolver as MerkleWitnessResolver, NodeStatusResolver, @@ -99,8 +98,7 @@ export async function startServer() { OpenTelemetryServer, Mempool: PrivateMempool, - GraphqlServer, - LocalTaskWorkerModule: LocalTaskWorkerModule.from( + WorkerModule: WorkerModule.from( VanillaTaskWorkerModules.withoutSettlement() ), @@ -151,19 +149,14 @@ export async function startServer() { }, Sequencer: { - GraphqlServer: { - port: 8080, - host: "0.0.0.0", - graphiql: true, - }, SequencerStartupModule: {}, - // SettlementModule: { - // address: PrivateKey.random().toPublicKey(), - // feepayer: PrivateKey.random(), - // }, - Graphql: { + containerConfig: { + port: 8080, + host: "0.0.0.0", + graphiql: true, + }, QueryGraphqlModule: {}, MempoolResolver: {}, BatchStorageResolver: {}, @@ -205,13 +198,11 @@ export async function startServer() { Mempool: {}, BatchProducerModule: {}, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), BaseLayer: {}, TaskQueue: {}, - BlockProducerModule: { - allowEmptyBlock: true, - }, + BlockProducerModule: {}, BlockTrigger: { blockInterval: 10000, diff --git a/packages/stack/src/scripts/worker/sequencer.ts b/packages/stack/src/scripts/worker/sequencer.ts index db0a3433d..a7c2eb723 100644 --- a/packages/stack/src/scripts/worker/sequencer.ts +++ b/packages/stack/src/scripts/worker/sequencer.ts @@ -9,14 +9,9 @@ import { InMemoryDatabase, MinaBaseLayer, TimedBlockTrigger, - DatabasePruneModule, AppChain, } from "@proto-kit/sequencer"; -import { - VanillaGraphqlModules, - GraphqlSequencerModule, - GraphqlServer, -} from "@proto-kit/api"; +import { VanillaGraphqlModules, GraphqlSequencerModule } from "@proto-kit/api"; import { app } from "./app"; @@ -29,8 +24,6 @@ export const sequencer = AppChain.from({ Database: InMemoryDatabase, BaseLayer: MinaBaseLayer, BlockTrigger: TimedBlockTrigger, - DatabasePruneModule: DatabasePruneModule, - GraphqlServer: GraphqlServer, Graphql: GraphqlSequencerModule.from(VanillaGraphqlModules.with({})), }) ), @@ -62,13 +55,12 @@ sequencer.configure({ }, }, SequencerStartupModule: {}, - GraphqlServer: { - host: "0.0.0.0", - port: 8080, - graphiql: true, - }, - Graphql: { + containerConfig: { + host: "0.0.0.0", + port: 8080, + graphiql: true, + }, QueryGraphqlModule: {}, MempoolResolver: {}, BatchStorageResolver: {}, diff --git a/packages/stack/test-integration/caching/caching.test.ts b/packages/stack/test-integration/caching/caching.test.ts index 896cdf645..5d0d33b08 100644 --- a/packages/stack/test-integration/caching/caching.test.ts +++ b/packages/stack/test-integration/caching/caching.test.ts @@ -20,7 +20,7 @@ import { BlockProducerModule, InMemoryDatabase, LocalTaskQueue, - LocalTaskWorkerModule, + WorkerModule, ManualBlockTrigger, NoopBaseLayer, PrivateMempool, @@ -49,7 +49,7 @@ export async function startAppChain() { Database: InMemoryDatabase, Mempool: PrivateMempool, - LocalTaskWorkerModule: LocalTaskWorkerModule.from( + WorkerModule: WorkerModule.from( VanillaTaskWorkerModules.withoutSettlement() ), @@ -92,13 +92,11 @@ export async function startAppChain() { Mempool: {}, BatchProducerModule: {}, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), BaseLayer: {}, TaskQueue: {}, - BlockProducerModule: { - allowEmptyBlock: true, - }, + BlockProducerModule: {}, BlockTrigger: {}, diff --git a/packages/stack/test/graphql/graphql-server.ts b/packages/stack/test/graphql/graphql-server.ts index 3318b9c7f..157faf92e 100644 --- a/packages/stack/test/graphql/graphql-server.ts +++ b/packages/stack/test/graphql/graphql-server.ts @@ -20,7 +20,7 @@ import { BatchProducerModule, InMemoryDatabase, LocalTaskQueue, - LocalTaskWorkerModule, + WorkerModule, NoopBaseLayer, PrivateMempool, Sequencer, @@ -32,7 +32,6 @@ import { import { BatchStorageResolver, GraphqlSequencerModule, - GraphqlServer, MempoolResolver, MerkleWitnessResolver, NodeStatusResolver, @@ -60,8 +59,7 @@ export async function startGraphqlServer() { // Database: PrismaRedisDatabase, Mempool: PrivateMempool, - GraphqlServer, - LocalTaskWorkerModule: LocalTaskWorkerModule.from( + WorkerModule: WorkerModule.from( VanillaTaskWorkerModules.withoutSettlement() ), @@ -108,11 +106,6 @@ export async function startGraphqlServer() { }, Sequencer: { - GraphqlServer: { - port: 8080, - host: "0.0.0.0", - graphiql: true, - }, SequencerStartupModule: {}, // SettlementModule: { @@ -121,6 +114,11 @@ export async function startGraphqlServer() { // }, Graphql: { + containerConfig: { + port: 8080, + host: "0.0.0.0", + graphiql: true, + }, QueryGraphqlModule: {}, MempoolResolver: {}, BatchStorageResolver: {}, @@ -150,13 +148,11 @@ export async function startGraphqlServer() { Mempool: {}, BatchProducerModule: {}, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + WorkerModule: VanillaTaskWorkerModules.defaultConfig(), BaseLayer: {}, TaskQueue: {}, - BlockProducerModule: { - allowEmptyBlock: true, - }, + BlockProducerModule: {}, BlockTrigger: {}, }, diff --git a/packages/stack/test/graphql/graphql.test.ts b/packages/stack/test/graphql/graphql.test.ts index 068acf5c8..7e0e3955b 100644 --- a/packages/stack/test/graphql/graphql.test.ts +++ b/packages/stack/test/graphql/graphql.test.ts @@ -68,9 +68,7 @@ function prepareClient() { }, }, - Sequencer: { - Mempool: {}, - }, + Sequencer: {}, TransactionSender: {}, QueryTransportModule: {},