From 2c5bde8213ca7d77fc8be9ec55cb7ad3ed0ad2cf Mon Sep 17 00:00:00 2001 From: stanlou Date: Tue, 20 Jan 2026 03:25:43 +0100 Subject: [PATCH 1/4] feat: add default modules and configurations for sequencer presets --- package-lock.json | 4 + packages/stack/package.json | 6 +- packages/stack/src/index.ts | 4 + packages/stack/src/presets/app-chain/index.ts | 122 ++++ packages/stack/src/presets/config.ts | 193 ++++++ packages/stack/src/presets/modules/index.ts | 619 ++++++++++++++++++ packages/stack/src/presets/modules/types.ts | 86 +++ packages/stack/src/presets/modules/utils.ts | 381 +++++++++++ packages/stack/src/presets/sequencer/index.ts | 136 ++++ 9 files changed, 1550 insertions(+), 1 deletion(-) create mode 100644 packages/stack/src/presets/app-chain/index.ts create mode 100644 packages/stack/src/presets/config.ts create mode 100644 packages/stack/src/presets/modules/index.ts create mode 100644 packages/stack/src/presets/modules/types.ts create mode 100644 packages/stack/src/presets/modules/utils.ts create mode 100644 packages/stack/src/presets/sequencer/index.ts diff --git a/package-lock.json b/package-lock.json index 10d879a4e..f73837ac0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27932,6 +27932,8 @@ "version": "0.1.1-develop.833+397881ed", "license": "MIT", "dependencies": { + "@prisma/client": "^5.19.1", + "mina-fungible-token": "^1.1.0", "reflect-metadata": "^0.1.13" }, "devDependencies": { @@ -27941,9 +27943,11 @@ "@proto-kit/api": "*", "@proto-kit/common": "*", "@proto-kit/deployment": "*", + "@proto-kit/indexer": "*", "@proto-kit/library": "*", "@proto-kit/module": "*", "@proto-kit/persistance": "*", + "@proto-kit/processor": "*", "@proto-kit/protocol": "*", "@proto-kit/sdk": "*", "@proto-kit/sequencer": "*", diff --git a/packages/stack/package.json b/packages/stack/package.json index 2851234e1..e983b9fe9 100644 --- a/packages/stack/package.json +++ b/packages/stack/package.json @@ -28,6 +28,8 @@ "@proto-kit/protocol": "*", "@proto-kit/sdk": "*", "@proto-kit/sequencer": "*", + "@proto-kit/indexer": "*", + "@proto-kit/processor": "*", "o1js": "^2.10.0", "tsyringe": "^4.10.0" }, @@ -35,7 +37,9 @@ "@jest/globals": "^29.5.0" }, "dependencies": { - "reflect-metadata": "^0.1.13" + "reflect-metadata": "^0.1.13", + "@prisma/client": "^5.19.1", + "mina-fungible-token": "^1.1.0" }, "gitHead": "397881ed5d8f98f5005bcd7be7f5a12b3bc6f956" } diff --git a/packages/stack/src/index.ts b/packages/stack/src/index.ts index 35d49ee83..3c5da028c 100644 --- a/packages/stack/src/index.ts +++ b/packages/stack/src/index.ts @@ -1 +1,5 @@ export * from "./scripts/graphql/server"; +export * from "./presets/app-chain"; +export * from "./presets/sequencer"; +export * from "./presets/config"; +export * from "./presets/modules"; \ No newline at end of file diff --git a/packages/stack/src/presets/app-chain/index.ts b/packages/stack/src/presets/app-chain/index.ts new file mode 100644 index 000000000..48db076cc --- /dev/null +++ b/packages/stack/src/presets/app-chain/index.ts @@ -0,0 +1,122 @@ +import { ModulesConfig, RecursivePartial } from "@proto-kit/common"; +import { Runtime, RuntimeModulesRecord } from "@proto-kit/module"; +import { + MandatoryProtocolModulesRecord, + Protocol, + ProtocolModulesRecord, +} from "@proto-kit/protocol"; +import { + AppChain, + AppChainModulesRecord, + SequencerModulesRecord, +} from "@proto-kit/sequencer"; +import { DefaultModules, DefaultConfigs } from "../modules"; +import { DefaultSequencer, DefaultSequencerConfig } from "../sequencer"; + +export class DefaultAppChain { + static inmemory( + runtimeModules: RuntimeModulesRecord, + protocolModules: ProtocolModulesRecord & MandatoryProtocolModulesRecord, + options?: { + overrideAppChainModules?: Partial; + settlementEnabled?: boolean; + overrideSequencerModules?: Partial; + } + ) { + return AppChain.from({ + Runtime: Runtime.from(runtimeModules), + Protocol: Protocol.from(protocolModules), + Sequencer: DefaultSequencer.inmemory({ + settlementEnabled: options?.settlementEnabled, + overrideModules: options?.overrideSequencerModules, + }), + ...DefaultModules.appChainBase(), + ...options?.overrideAppChainModules, + }); + } + static development( + runtimeModules: RuntimeModulesRecord, + protocolModules: ProtocolModulesRecord & MandatoryProtocolModulesRecord, + options?: { + overrideAppChainModules?: Partial; + settlementEnabled?: boolean; + overrideSequencerModules?: Partial; + } + ) { + return AppChain.from({ + Runtime: Runtime.from(runtimeModules), + Protocol: Protocol.from(protocolModules), + Sequencer: DefaultSequencer.development({ + settlementEnabled: options?.settlementEnabled, + overrideModules: options?.overrideSequencerModules, + }), + ...DefaultModules.appChainBase(), + ...options?.overrideAppChainModules, + }); + } + static sovereign( + runtimeModules: RuntimeModulesRecord, + protocolModules: ProtocolModulesRecord & MandatoryProtocolModulesRecord, + options?: { + overrideAppChainModules?: Partial; + settlementEnabled?: boolean; + overrideSequencerModules?: Partial; + } + ) { + return AppChain.from({ + Runtime: Runtime.from(runtimeModules), + Protocol: Protocol.from(protocolModules), + Sequencer: DefaultSequencer.sovereign({ + settlementEnabled: options?.settlementEnabled, + overrideModules: options?.overrideSequencerModules, + }), + ...DefaultModules.appChainBase(), + ...options?.overrideAppChainModules, + }); + } +} + +export class DefaultAppChainConfig { + static inmemory(options?: { + overrideAppChainConfig?: RecursivePartial>; + settlementEnabled?: boolean; + overrideSequencerConfig?: RecursivePartial>; + }) { + return { + Sequencer: DefaultSequencerConfig.inmemory({ + settlementEnabled: options?.settlementEnabled, + overrideConfig: options?.overrideSequencerConfig, + }), + ...DefaultConfigs.appChainBase(), + ...options?.overrideAppChainConfig, + }; + } + static development(options?: { + overrideAppChainConfig?: RecursivePartial>; + settlementEnabled?: boolean; + overrideSequencerConfig?: RecursivePartial>; + }) { + return { + Sequencer: DefaultSequencerConfig.development({ + settlementEnabled: options?.settlementEnabled, + overrideConfig: options?.overrideSequencerConfig, + }), + ...DefaultConfigs.appChainBase(), + ...options?.overrideAppChainConfig, + }; + } + static sovereign(options?: { + overrideAppChainConfig?: RecursivePartial>; + settlementEnabled?: boolean; + overrideSequencerConfig?: RecursivePartial>; + }) { + return { + Sequencer: DefaultSequencerConfig.sovereign({ + settlementEnabled: options?.settlementEnabled, + overrideConfig: options?.overrideSequencerConfig, + }), + ...DefaultConfigs.appChainBase(), + ...options?.overrideAppChainConfig, + }; + } +} diff --git a/packages/stack/src/presets/config.ts b/packages/stack/src/presets/config.ts new file mode 100644 index 000000000..835402150 --- /dev/null +++ b/packages/stack/src/presets/config.ts @@ -0,0 +1,193 @@ +export const inmemoryConfig = { + PROTOKIT_BLOCK_INTERVAL: 5000, + PROTOKIT_GRAPHQL_PORT: 8080, + PROTOKIT_GRAPHQL_HOST: "localhost", + PROTOKIT_GRAPHIQL_ENABLED: true, +}; + +export const developmentConfig = { + PROTOKIT_PROOFS_ENABLED: false, + PROTOKIT_SHOULD_ATTEMPT_DB_MIGRATION: true, + PROTOKIT_SHOULD_ATTEMPT_INDEXER_DB_MIGRATION: true, + PROTOKIT_SHOULD_ATTEMPT_PROCESSOR_DB_MIGRATION: true, + PROTOKIT_PRUNE_ON_STARTUP: false, + PROTOKIT_LOG_LEVEL: "INFO", + + PROTOKIT_BLOCK_INTERVAL: 30000, + PROTOKIT_SETTLEMENT_INTERVAL: 60000, + PROTOKIT_SETTLEMENT_ENABLED: true, + + REDIS_HOST: "localhost", + REDIS_PORT: 6379, + REDIS_PASSWORD: "password", + + DATABASE_URL: + "postgresql://admin:password@localhost:5432/protokit?schema=public", + + INDEXER_DATABASE_URL: + "postgresql://admin:password@localhost:5433/protokit-indexer?schema=public", + + PROCESSOR_DATABASE_URL: + "postgresql://admin:password@localhost:5434/protokit-processor?schema=public", + + PROTOKIT_GRAPHQL_HOST: "0.0.0.0", + PROTOKIT_GRAPHQL_PORT: 8080, + PROTOKIT_GRAPHIQL_ENABLED: true, + + PROTOKIT_INDEXER_GRAPHQL_HOST: "0.0.0.0", + PROTOKIT_INDEXER_GRAPHQL_PORT: 8081, + PROTOKIT_INDEXER_GRAPHIQL_ENABLED: true, + + PROTOKIT_PROCESSOR_GRAPHQL_HOST: "0.0.0.0", + PROTOKIT_PROCESSOR_GRAPHQL_PORT: 8082, + PROTOKIT_PROCESSOR_GRAPHIQL_ENABLED: true, + PROTOKIT_PROCESSOR_INDEXER_GRAPHQL_HOST: "0.0.0.0", + + MINA_NETWORK: "lightnet", + MINA_NODE_GRAPHQL_HOST: "http://localhost", + MINA_NODE_GRAPHQL_PORT: 8083, + + MINA_ARCHIVE_GRAPHQL_HOST: "http://localhost", + MINA_ARCHIVE_GRAPHQL_PORT: 8085, + + MINA_ACCOUNT_MANAGER_HOST: "http://localhost", + MINA_ACCOUNT_MANAGER_PORT: 8084, + MINA_EXPLORER_PORT: 3001, + + PROTOKIT_TRANSACTION_FEE_RECIPIENT_PRIVATE_KEY: + "EKEssvj33MMBCg2tcybTzL32nTKbbwFHm6yUxd3JassdhL3J5aT8", + PROTOKIT_TRANSACTION_FEE_RECIPIENT_PUBLIC_KEY: + "B62qk4sNnzZqqjHp8YQXZUV3dBpnjiNieJVnsuh7mD2bMJ9PdbskH5H", + + PROTOKIT_SEQUENCER_PRIVATE_KEY: + "EKEdKhgUHMuDvwWJEg2TdCMCeiTSd9hh2HrEr6uYJfPVuwur1s43", + PROTOKIT_SEQUENCER_PUBLIC_KEY: + "B62qizW6aroTxQorJz4ywVNZom4jA6W4QPPCK3wLeyhnJHtVStUNniL", + + PROTOKIT_SETTLEMENT_CONTRACT_PRIVATE_KEY: + "EKErS9gYHZNawqKuwfMiwYYJtNptCrvca491QEvB3tz8sFsS5w66", + PROTOKIT_SETTLEMENT_CONTRACT_PUBLIC_KEY: + "B62qjKhzrvDgTPXCp34ozmpFSx4sC9owZe6eDzhdGPdoiUbGPmBkHTt", + + PROTOKIT_DISPATCHER_CONTRACT_PRIVATE_KEY: + "EKF9Ei5G9PeB5ULMh9R6P5LfWX2gs15XxPNsect1pbcbMY9vs6v7", + PROTOKIT_DISPATCHER_CONTRACT_PUBLIC_KEY: + "B62qmAzUJ1jqcsEf2V3K1k2Ec4MLsEKnodEvvJ5uweTFSLYEUALe1zs", + + PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY: + "EKFKTGqWU2egLKhMgoxX8mQ21zXSE1RZYkY82mmK9F3BxdSA7E5M", + PROTOKIT_MINA_BRIDGE_CONTRACT_PUBLIC_KEY: + "B62qn8XRkWcaBvv6F7kvarKs4cViaKRMbTUHT8FrDXLnvxuV6n7CHsN", + + PROTOKIT_CUSTOM_TOKEN_PRIVATE_KEY: + "EKFZHQSo5YdrcU7neDaNZruYHvCiNncvdZyKXuS6MDCW1fyCFKDP", + + PROTOKIT_CUSTOM_TOKEN_ADMIN_PRIVATE_KEY: + "EKENQ2QRc4gAJkZjQXU86ZS9MDm1e7HFiNN6LgRJnniHJt1WXDn1", + + PROTOKIT_CUSTOM_TOKEN_BRIDGE_PRIVATE_KEY: + "EKENQ2QRc4gAJkZjQXU86ZS9MDm1e7HFiNN6LgRJnniHJt1WXDn1", + + TEST_ACCOUNT_1_PRIVATE_KEY: + "EKF5p3wQTFd4tRBiGicRf93yXK82bcRryokC1qoazRM6wq6gMzWJ", + TEST_ACCOUNT_1_PUBLIC_KEY: + "B62qkVfEwyfkm5yucHEqrRjxbyx98pgdWz82pHv7LYq9Qigs812iWZ8", + + OPEN_TELEMETRY_TRACING_ENABLED: true, + OPEN_TELEMETRY_TRACING_URL: "http://localhost:4318", + + OPEN_TELEMETRY_METRICS_ENABLED: true, + OPEN_TELEMETRY_METRICS_HOST: "0.0.0.0", + OPEN_TELEMETRY_METRICS_PORT: 4320, + OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY: 10, + +}; + +export const sovereignConfig = { + PROTOKIT_BLOCK_INTERVAL: 10000, + PROTOKIT_SETTLEMENT_INTERVAL: 30000, + PROTOKIT_SETTLEMENT_ENABLED: true, + + PROTOKIT_SHOULD_ATTEMPT_DB_MIGRATION: true, + PROTOKIT_SHOULD_ATTEMPT_INDEXER_DB_MIGRATION: true, + PROTOKIT_SHOULD_ATTEMPT_PROCESSOR_DB_MIGRATION: true, + + PROTOKIT_PRUNE_ON_STARTUP: false, + PROTOKIT_LOG_LEVEL: "INFO", + + REDIS_HOST: "redis", + REDIS_PORT: 6379, + REDIS_PASSWORD: "password", + + DATABASE_URL: + "postgresql://admin:password@postgres:5432/protokit?schema=public", + + INDEXER_DATABASE_URL: + "postgresql://admin:password@indexer-postgres:5432/protokit-indexer?schema=public", + + PROCESSOR_DATABASE_URL: + "postgresql://admin:password@processor-postgres:5432/protokit-processor?schema=public", + + PROTOKIT_GRAPHQL_HOST: "0.0.0.0", + PROTOKIT_GRAPHQL_PORT: 8080, + PROTOKIT_GRAPHIQL_ENABLED: true, + + PROTOKIT_INDEXER_GRAPHQL_HOST: "0.0.0.0", + PROTOKIT_INDEXER_GRAPHQL_PORT: 8081, + PROTOKIT_INDEXER_GRAPHIQL_ENABLED: true, + + PROTOKIT_PROCESSOR_GRAPHQL_HOST: "0.0.0.0", + PROTOKIT_PROCESSOR_GRAPHQL_PORT: 8082, + PROTOKIT_PROCESSOR_GRAPHIQL_ENABLED: true, + PROTOKIT_PROCESSOR_INDEXER_GRAPHQL_HOST: "indexer", + + MINA_NETWORK: "lightnet", + MINA_NODE_GRAPHQL_HOST: "http://lightnet", + MINA_NODE_GRAPHQL_PORT: 8080, + + MINA_ARCHIVE_GRAPHQL_HOST: "http://lightnet", + MINA_ARCHIVE_GRAPHQL_PORT: 8282, + + MINA_ACCOUNT_MANAGER_HOST: "http://lightnet", + MINA_ACCOUNT_MANAGER_PORT: 8084, + MINA_EXPLORER_PORT: 3001, + + PROTOKIT_TRANSACTION_FEE_RECIPIENT_PRIVATE_KEY: + "EKEssvj33MMBCg2tcybTzL32nTKbbwFHm6yUxd3JassdhL3J5aT8", + PROTOKIT_TRANSACTION_FEE_RECIPIENT_PUBLIC_KEY: + "B62qk4sNnzZqqjHp8YQXZUV3dBpnjiNieJVnsuh7mD2bMJ9PdbskH5H", + + PROTOKIT_SEQUENCER_PRIVATE_KEY: + "EKEdKhgUHMuDvwWJEg2TdCMCeiTSd9hh2HrEr6uYJfPVuwur1s43", + PROTOKIT_SEQUENCER_PUBLIC_KEY: + "B62qizW6aroTxQorJz4ywVNZom4jA6W4QPPCK3wLeyhnJHtVStUNniL", + + PROTOKIT_SETTLEMENT_CONTRACT_PRIVATE_KEY: + "EKErS9gYHZNawqKuwfMiwYYJtNptCrvca491QEvB3tz8sFsS5w66", + PROTOKIT_SETTLEMENT_CONTRACT_PUBLIC_KEY: + "B62qjKhzrvDgTPXCp34ozmpFSx4sC9owZe6eDzhdGPdoiUbGPmBkHTt", + + PROTOKIT_DISPATCHER_CONTRACT_PRIVATE_KEY: + "EKF9Ei5G9PeB5ULMh9R6P5LfWX2gs15XxPNsect1pbcbMY9vs6v7", + PROTOKIT_DISPATCHER_CONTRACT_PUBLIC_KEY: + "B62qmAzUJ1jqcsEf2V3K1k2Ec4MLsEKnodEvvJ5uweTFSLYEUALe1zs", + + PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY: + "EKFKTGqWU2egLKhMgoxX8mQ21zXSE1RZYkY82mmK9F3BxdSA7E5M", + PROTOKIT_MINA_BRIDGE_CONTRACT_PUBLIC_KEY: + "B62qn8XRkWcaBvv6F7kvarKs4cViaKRMbTUHT8FrDXLnvxuV6n7CHsN", + + TEST_ACCOUNT_1_PRIVATE_KEY: + "EKF5p3wQTFd4tRBiGicRf93yXK82bcRryokC1qoazRM6wq6gMzWJ", + TEST_ACCOUNT_1_PUBLIC_KEY: + "B62qkVfEwyfkm5yucHEqrRjxbyx98pgdWz82pHv7LYq9Qigs812iWZ8", + + OPEN_TELEMETRY_TRACING_ENABLED: true, + OPEN_TELEMETRY_TRACING_URL: "http://otel-collector:4317", + + OPEN_TELEMETRY_METRICS_ENABLED: true, + OPEN_TELEMETRY_METRICS_HOST: "0.0.0.0", + OPEN_TELEMETRY_METRICS_PORT: 4320, + OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY: 10, + +}; \ No newline at end of file diff --git a/packages/stack/src/presets/modules/index.ts b/packages/stack/src/presets/modules/index.ts new file mode 100644 index 000000000..4561e14e1 --- /dev/null +++ b/packages/stack/src/presets/modules/index.ts @@ -0,0 +1,619 @@ +import { + VanillaGraphqlModules, + GraphqlSequencerModule, + GraphqlServer, + OpenTelemetryServer, +} from "@proto-kit/api"; +import { + PrivateMempool, + SequencerModulesRecord, + TimedBlockTrigger, + BlockProducerModule, + SequencerStartupModule, + LocalTaskWorkerModule, + VanillaTaskWorkerModules, + MinaBaseLayer, + ConstantFeeStrategy, + BatchProducerModule, + SettlementModule, + DatabasePruneModule, + InMemoryDatabase, + LocalTaskQueue, +} from "@proto-kit/sequencer"; +import { + IndexerNotifier, + GeneratedResolverFactoryGraphqlModule, + IndexBlockTask, +} from "@proto-kit/indexer"; +import { PrivateKey } from "o1js"; +import { PrismaRedisDatabase } from "@proto-kit/persistance"; +import { BullQueue } from "@proto-kit/deployment"; +import { + TimedProcessorTrigger, + BlockFetching, + HandlersExecutor, + ResolverFactoryGraphqlModule, + HandlersRecord, + BasePrismaClient, +} from "@proto-kit/processor"; +import { + BlockStorageNetworkStateModule, + InMemoryTransactionSender, + StateServiceQueryModule, +} from "@proto-kit/sdk"; +import { AppChainModulesRecord } from "@proto-kit/sequencer"; +import { + buildCustomTokenConfig, + buildSettlementTokenConfig, + definePreset, + orderModulesByDependencies, + parseApiEnv, + parseCoreEnv, + parseMetricsEnv, + parseSettlementEnv, + parseIndexerEnv, + parseProcessorEnv, + parseDatabaseEnv, + parseDatabasePruneEnv, + parseGraphqlServerEnv, + parseRedisEnv, + resolveEnv, +} from "./utils"; +import { NonEmptyArray } from "type-graphql"; +import { + Environment, + ModuleOverrides, + ApiEnv, + ConfigOverrides, + CoreEnv, + MetricsEnv, + IndexerEnv, + ProcessorEnv, + SettlementEnv, + DatabaseEnv, + TaskQueueEnv, + DatabasePruneEnv, + GraphqlServerEnv, + RedisEnv, +} from "./types"; + +export class DefaultModules { + static api(options?: { + overrides?: ModuleOverrides; + }): SequencerModulesRecord { + return definePreset( + { + GraphqlServer, + Graphql: GraphqlSequencerModule.from(VanillaGraphqlModules.with({})), + }, + options?.overrides + ); + } + static core(options?: { + overrides?: ModuleOverrides; + settlementEnabled?: boolean; + }): SequencerModulesRecord { + return definePreset( + { + ...DefaultModules.api(), + Mempool: PrivateMempool, + BlockProducerModule, + BlockTrigger: TimedBlockTrigger, + SequencerStartupModule, + LocalTaskWorkerModule: LocalTaskWorkerModule.from( + VanillaTaskWorkerModules.withoutSettlement() + ), + ...(options?.settlementEnabled ? DefaultModules.settlement() : {}), + }, + options?.overrides + ); + } + static metrics(options?: { + overrides?: ModuleOverrides; + }): SequencerModulesRecord { + return definePreset( + { + OpenTelemetryServer, + }, + options?.overrides + ); + } + static settlement(options?: { + overrides?: ModuleOverrides; + }): SequencerModulesRecord { + return definePreset( + { + BaseLayer: MinaBaseLayer, + FeeStrategy: ConstantFeeStrategy, + BatchProducerModule, + SettlementModule, + LocalTaskWorkerModule: LocalTaskWorkerModule.from( + VanillaTaskWorkerModules.allTasks() + ), + }, + options?.overrides + ); + } + static sequencerIndexer(options?: { + overrides?: ModuleOverrides; + }): SequencerModulesRecord { + return definePreset( + { + IndexerNotifier, + }, + options?.overrides + ); + } + static indexer(options?: { overrides?: ModuleOverrides }) { + return definePreset( + { + Database: PrismaRedisDatabase, + TaskQueue: BullQueue, + TaskWorker: LocalTaskWorkerModule.from({ + IndexBlockTask, + }), + GraphqlServer, + Graphql: GraphqlSequencerModule.from({ + GeneratedResolverFactory: GeneratedResolverFactoryGraphqlModule, + }), + }, + options?.overrides + ); + } + static processor( + resolvers: NonEmptyArray, + handlers: HandlersRecord, + options?: { overrides?: ModuleOverrides } + ) { + return definePreset( + { + GraphqlServer, + GraphqlSequencerModule: GraphqlSequencerModule.from({ + ResolverFactory: ResolverFactoryGraphqlModule.from(resolvers), + }), + HandlersExecutor: HandlersExecutor.from(handlers), + BlockFetching, + Trigger: TimedProcessorTrigger, + }, + options?.overrides + ); + } + static database(options?: { + overrides?: ModuleOverrides; + preset?: Environment; + }): SequencerModulesRecord { + const preset = options?.preset ?? "inmemory"; + + return definePreset( + { + Database: + preset === "inmemory" ? InMemoryDatabase : PrismaRedisDatabase, + }, + options?.overrides + ); + } + static taskQueue(options?: { + overrides?: ModuleOverrides; + preset?: Environment; + }): SequencerModulesRecord { + const preset = options?.preset ?? "inmemory"; + return definePreset( + { + TaskQueue: preset === "inmemory" ? LocalTaskQueue : BullQueue, + }, + options?.overrides + ); + } + static databasePrune(options?: { + overrides?: ModuleOverrides; + }): SequencerModulesRecord { + return definePreset( + { + DatabasePruneModule, + }, + options?.overrides + ); + } + static worker(options?: { + overrides?: ModuleOverrides; + }): SequencerModulesRecord { + return definePreset( + { + TaskQueue: BullQueue, + LocalTaskWorkerModule: LocalTaskWorkerModule.from( + VanillaTaskWorkerModules.allTasks() + ), + }, + options?.overrides + ); + } + static appChainBase(options?: { + overrides?: Partial; + }): AppChainModulesRecord { + return definePreset( + { + TransactionSender: InMemoryTransactionSender, + QueryTransportModule: StateServiceQueryModule, + NetworkStateTransportModule: BlockStorageNetworkStateModule, + }, + options?.overrides + ) as AppChainModulesRecord; + } + static settlementScript(options?: { + overrides?: ModuleOverrides; + }): SequencerModulesRecord { + return definePreset( + { + ...DefaultModules.settlement(), + Mempool: PrivateMempool, + TaskQueue: LocalTaskQueue, + SequencerStartupModule, + }, + options?.overrides + ); + } + static ordered(modules: any) { + return orderModulesByDependencies(modules); + } +} +export class DefaultConfigs { + static api(options?: { + preset?: Environment; + envs?: Partial; + overrides?: ConfigOverrides; + }): ConfigOverrides { + return definePreset( + { + Graphql: VanillaGraphqlModules.defaultConfig(), + GraphqlServer: DefaultConfigs.graphqlServer({ + type: "protokit", + preset: options?.preset, + envs: options?.envs, + }), + }, + options?.overrides + ); + } + static core(options?: { + preset?: Environment; + envs?: Partial & Partial & Partial; + overrides?: ConfigOverrides; + settlementEnabled?: boolean; + }): ConfigOverrides { + const config = resolveEnv(options?.preset, options?.envs); + const parsed = parseCoreEnv( + { ...config, ...options?.envs }, + options?.settlementEnabled + ); + const apiConfig = DefaultConfigs.api({ + preset: options?.preset, + envs: options?.envs, + }); + const settlementConfig = options?.settlementEnabled + ? DefaultConfigs.settlement({ + preset: options?.preset, + envs: options?.envs, + }) + : {}; + const blockTriggerConfig = { + blockInterval: parsed.blockInterval, + produceEmptyBlocks: true, + ...(options?.settlementEnabled + ? { + settlementInterval: parsed.settlementInterval, + settlementTokenConfig: buildSettlementTokenConfig( + parsed.minaBridgeKey!, + buildCustomTokenConfig( + parsed.customTokenKey, + parsed.customTokenBridgeKey + ) + ), + } + : { settlementTokenConfig: {} }), + }; + + return definePreset( + { + ...apiConfig, + Mempool: {}, + BlockProducerModule: {}, + BlockTrigger: blockTriggerConfig, + SequencerStartupModule: {}, + LocalTaskWorkerModule: VanillaGraphqlModules.defaultConfig(), + ...settlementConfig, + }, + options?.overrides + ); + } + static metrics(options?: { + preset?: Environment; + envs?: MetricsEnv; + overrides?: ConfigOverrides; + }): ConfigOverrides { + const configs = resolveEnv(options?.preset, options?.envs); + const parsed = parseMetricsEnv(configs); + return definePreset( + { + OpenTelemetryServer: { + metrics: { + enabled: parsed.metricsEnabled, + prometheus: { + host: parsed.metricsHost, + port: parsed.metricsPort, + appendTimestamp: true, + }, + nodeScrapeInterval: parsed.metricsScrapingFrequency, + }, + tracing: { + enabled: parsed.tracingEnabled, + otlp: { + url: parsed.tracingUrl, + }, + }, + }, + }, + options?.overrides + ); + } + static sequencerIndexer(options?: { + overrides?: ConfigOverrides; + }): ConfigOverrides { + return definePreset({ IndexerNotifier: {} }, options?.overrides); + } + static indexer(options?: { + preset?: Environment; + envs?: Partial; + overrides?: ConfigOverrides; + }): ConfigOverrides { + const config = resolveEnv(options?.preset, options?.envs); + const parsed = parseIndexerEnv(config); + const redisConfig = DefaultConfigs.redis({ + preset: options?.preset, + envs: options?.envs, + }); + const databaseConfig = DefaultConfigs.database({ + preset: options?.preset, + envs: options?.envs, + }); + const graphqlServerConfig = DefaultConfigs.graphqlServer({ + type: "indexer", + preset: options?.preset, + envs: options?.envs, + }); + + return definePreset( + { + ...databaseConfig, + TaskQueue: redisConfig.TaskQueue, + TaskWorker: { + IndexBlockTask: {}, + }, + ...graphqlServerConfig, + Graphql: { + GeneratedResolverFactory: {}, + }, + }, + options?.overrides + ); + } + static processor(options?: { + preset?: Environment; + envs?: Partial; + overrides?: ConfigOverrides; + }): ConfigOverrides { + const config = resolveEnv(options?.preset, options?.envs); + const parsed = parseProcessorEnv(config); + const graphqlServerConfig = DefaultConfigs.graphqlServer({ + type: "processor", + preset: options?.preset, + envs: options?.envs, + }); + return definePreset( + { + HandlersExecutor: {}, + BlockFetching: { + url: `http://${parsed.processorIndexerGraphqlHost}:${parsed.indexerGraphqlPort}`, + }, + Trigger: { + interval: (parsed.blockInterval ?? 5000) / 5, + }, + ...graphqlServerConfig, + GraphqlSequencerModule: { + ResolverFactory: {}, + }, + }, + options?.overrides + ); + } + static settlement(options?: { + preset?: Environment; + envs?: Partial; + overrides?: ConfigOverrides; + }): ConfigOverrides { + const config = resolveEnv(options?.preset, options?.envs); + const parsed = parseSettlementEnv(config); + + return definePreset( + { + BaseLayer: { + network: { + type: parsed.network, + graphql: parsed.graphql, + archive: parsed.archive, + accountManager: parsed.accountManager, + }, + }, + SettlementModule: { + feepayer: PrivateKey.fromBase58(parsed.sequencerPrivateKey), + keys: { + settlement: PrivateKey.fromBase58( + parsed.settlementContractPrivateKey + ), + dispatch: PrivateKey.fromBase58( + parsed.dispatcherContractPrivateKey + ), + minaBridge: PrivateKey.fromBase58( + parsed.minaBridgeContractPrivateKey + ), + }, + }, + FeeStrategy: {}, + BatchProducerModule: {}, + }, + options?.overrides + ); + } + static database(options?: { + preset?: Environment; + envs?: Partial; + overrides?: ConfigOverrides; + }): ConfigOverrides { + const preset = options?.preset ?? "inmemory"; + if (preset === "inmemory") { + return { Database: definePreset({}, options?.overrides) }; + } + const config = resolveEnv(options?.preset, options?.envs); + const parsed = parseDatabaseEnv(config); + const redisConfig = DefaultConfigs.redis({ + preset: options?.preset, + envs: options?.envs, + }); + return { + Database: definePreset( + { + ...redisConfig, + prisma: { + connection: parsed.databaseUrl, + }, + }, + options?.overrides + ), + }; + } + static taskQueue(options?: { + preset?: Environment; + envs?: Partial; + overrides?: ConfigOverrides; + }): ConfigOverrides { + const preset = options?.preset ?? "inmemory"; + if (preset === "inmemory") { + return { + TaskQueue: definePreset({}, options?.overrides), + }; + } + const redisConfig = DefaultConfigs.redis({ + preset: options?.preset, + envs: options?.envs, + }); + + return { TaskQueue: definePreset(redisConfig, options?.overrides) }; + } + static databasePrune(options?: { + preset?: Environment; + envs?: Partial; + overrides?: ConfigOverrides; + }): ConfigOverrides { + const config = resolveEnv(options?.preset, options?.envs); + const parsed = parseDatabasePruneEnv(config); + + return { + DatabasePruneModule: definePreset( + { + pruneOnStartup: parsed.pruneOnStartup, + }, + options?.overrides + ), + }; + } + static graphqlServer(options?: { + preset?: Environment; + envs?: Partial; + overrides?: ConfigOverrides; + type?: "indexer" | "processor" | "protokit"; + }): ConfigOverrides { + const config = resolveEnv(options?.preset, options?.envs); + const parsed = parseGraphqlServerEnv(config, options?.type); + + return definePreset( + { + port: parsed.graphqlPort, + host: parsed.graphqlHost, + graphiql: parsed.graphiqlEnabled, + }, + options?.overrides + ); + } + static redis(options?: { + preset?: Environment; + envs?: Partial; + overrides?: ConfigOverrides; + }): ConfigOverrides { + const config = resolveEnv(options?.preset, options?.envs); + const parsed = parseRedisEnv(config); + + return { + redis: definePreset( + { + host: parsed.redisHost, + port: parsed.redisPort, + password: parsed.redisPassword, + }, + options?.overrides + ), + }; + } + static appChainBase(options?: { + overrides?: ConfigOverrides; + }): ConfigOverrides { + return definePreset( + { + QueryTransportModule: {}, + NetworkStateTransportModule: {}, + TransactionSender: {}, + }, + options?.overrides + ); + } + static worker(options?: { + preset?: Environment; + envs?: Partial; + overrides?: ConfigOverrides; + }): ConfigOverrides { + const redisConfig = DefaultConfigs.redis({ + preset: options?.preset, + envs: options?.envs, + overrides: { + db: 1, + }, + }); + + return definePreset( + { + TaskQueue: redisConfig, + LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + }, + options?.overrides + ); + } + static settlementScript(options?: { + preset?: Environment; + envs?: Partial; + overrides?: ConfigOverrides; + }): ConfigOverrides { + const settlementConfig = DefaultConfigs.settlement({ + preset: options?.preset, + envs: options?.envs, + }); + return definePreset( + { + ...settlementConfig, + SequencerStartupModule: {}, + TaskQueue: { + simulatedDuration: 0, + }, + Mempool: {}, + }, + options?.overrides + ); + } +} diff --git a/packages/stack/src/presets/modules/types.ts b/packages/stack/src/presets/modules/types.ts new file mode 100644 index 000000000..712511168 --- /dev/null +++ b/packages/stack/src/presets/modules/types.ts @@ -0,0 +1,86 @@ +import { RecursivePartial, ModulesConfig } from "@proto-kit/common"; +import { SequencerModulesRecord } from "@proto-kit/sequencer"; + +export type ModuleOverrides = Partial; +export type ConfigOverrides = RecursivePartial>; +export type Environment = "inmemory" | "development" | "sovereign"; +export type ApiEnv = { + PROTOKIT_GRAPHQL_PORT: number | string; + PROTOKIT_GRAPHQL_HOST: string; + PROTOKIT_GRAPHIQL_ENABLED: boolean | string; +}; +export type CoreEnv = { + PROTOKIT_BLOCK_INTERVAL: number | string; + PROTOKIT_SETTLEMENT_INTERVAL?: number | string; + PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY?: string; + PROTOKIT_CUSTOM_TOKEN_PRIVATE_KEY?: string; + PROTOKIT_CUSTOM_TOKEN_BRIDGE_PRIVATE_KEY?: string; +}; +export type MetricsEnv = { + OPEN_TELEMETRY_METRICS_ENABLED: boolean | string; + OPEN_TELEMETRY_METRICS_HOST: string; + OPEN_TELEMETRY_METRICS_PORT: number | string; + OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY: number | string; + OPEN_TELEMETRY_TRACING_ENABLED: boolean | string; + OPEN_TELEMETRY_TRACING_URL: string; +}; +export type SettlementEnv = { + MINA_NETWORK: string; + MINA_NODE_GRAPHQL_HOST: string; + MINA_NODE_GRAPHQL_PORT: number | string; + MINA_ARCHIVE_GRAPHQL_HOST: string; + MINA_ARCHIVE_GRAPHQL_PORT: number | string; + MINA_ACCOUNT_MANAGER_HOST: string; + MINA_ACCOUNT_MANAGER_PORT: number | string; + PROTOKIT_SEQUENCER_PRIVATE_KEY: string; + PROTOKIT_SETTLEMENT_CONTRACT_PRIVATE_KEY: string; + PROTOKIT_DISPATCHER_CONTRACT_PRIVATE_KEY: string; + PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY: string; +}; +export type IndexerEnv = { + REDIS_HOST: string; + REDIS_PORT: number | string; + REDIS_PASSWORD: string; + INDEXER_DATABASE_URL: string; + PROTOKIT_INDEXER_GRAPHQL_PORT: number | string; + PROTOKIT_INDEXER_GRAPHQL_HOST: string; + PROTOKIT_INDEXER_GRAPHIQL_ENABLED: boolean | string; +}; +export type ProcessorEnv = { + PROTOKIT_PROCESSOR_INDEXER_GRAPHQL_HOST: string; + PROTOKIT_INDEXER_GRAPHQL_PORT: number | string; + PROTOKIT_BLOCK_INTERVAL: number | string; + PROTOKIT_PROCESSOR_GRAPHQL_HOST: string; + PROTOKIT_PROCESSOR_GRAPHQL_PORT: number | string; + PROTOKIT_PROCESSOR_GRAPHIQL_ENABLED: boolean | string; +}; +export type DatabaseEnv = { + REDIS_HOST: string; + REDIS_PORT: number | string; + REDIS_PASSWORD: string; + DATABASE_URL: string; +}; +export type TaskQueueEnv = { + REDIS_HOST: string; + REDIS_PORT: number | string; + REDIS_PASSWORD: string; +}; +export type DatabasePruneEnv = { + PRUNE_ON_STARTUP?: boolean | string; +}; +export type GraphqlServerEnv = { + PROTOKIT_GRAPHQL_PORT?: number | string; + PROTOKIT_GRAPHQL_HOST?: string; + PROTOKIT_GRAPHIQL_ENABLED?: boolean | string; + PROTOKIT_INDEXER_GRAPHQL_HOST?: string; + PROTOKIT_INDEXER_GRAPHQL_PORT?: number | string; + PROTOKIT_INDEXER_GRAPHIQL_ENABLED?: boolean | string; + PROTOKIT_PROCESSOR_GRAPHQL_HOST?: string; + PROTOKIT_PROCESSOR_GRAPHQL_PORT?: number | string; + PROTOKIT_PROCESSOR_GRAPHIQL_ENABLED?: boolean | string; +}; +export type RedisEnv = { + REDIS_HOST: string; + REDIS_PORT: number | string; + REDIS_PASSWORD: string; +}; diff --git a/packages/stack/src/presets/modules/utils.ts b/packages/stack/src/presets/modules/utils.ts new file mode 100644 index 000000000..679b35165 --- /dev/null +++ b/packages/stack/src/presets/modules/utils.ts @@ -0,0 +1,381 @@ +import { PrivateKey, TokenId } from "o1js"; +import { developmentConfig, inmemoryConfig, sovereignConfig } from "../config"; +import { FungibleToken } from "mina-fungible-token"; +import { assertDefined } from "@proto-kit/common"; +import { + ApiEnv, + CoreEnv, + DatabaseEnv, + DatabasePruneEnv, + Environment, + GraphqlServerEnv, + IndexerEnv, + MetricsEnv, + ProcessorEnv, + RedisEnv, + SettlementEnv, + TaskQueueEnv, +} from "./types"; + +function ensureDefined(obj: Record, keys: string[]) { + keys.forEach((k) => assertDefined(obj[k], `${k} is required`)); +} +export function definePreset( + base: T, + overrides?: Partial +): T { + return { + ...base, + ...overrides, + }; +} +const MODULE_DEPENDENCIES: Record = { + Database: [], + TaskQueue: [], + OpenTelemetryServer: [], + BaseLayer: [], + FeeStrategy: [], + + Protocol: [], + Mempool: ["Database"], + BlockProducerModule: ["Database"], + + LocalTaskWorkerModule: ["TaskQueue"], + TaskWorker: ["TaskQueue"], + SequencerStartupModule: ["Database"], + BatchProducerModule: ["Database"], + BlockTrigger: ["BlockProducerModule", "BatchProducerModule"], + + SettlementModule: ["Database", "BaseLayer", "FeeStrategy"], + + DatabasePruneModule: ["Database"], + + Graphql: [], + GraphqlServer: [], + + IndexBlockTask: ["Database", "TaskQueue"], + IndexerNotifier: ["Database", "TaskQueue"], + GeneratedResolverFactory: [], + + BlockFetching: [], + HandlersExecutor: [], + Trigger: ["BlockFetching", "HandlersExecutor"], + ResolverFactory: [], +}; +export function orderModulesByDependencies( + modules: Record +): Record { + const moduleSet = new Set(Object.keys(modules)); + const ordered: Record = {}; + const visited = new Set(); + + function visit(name: string) { + if (!moduleSet.has(name) || visited.has(name)) return; + + const deps = MODULE_DEPENDENCIES[name] ?? []; + for (const dep of deps) { + visit(dep); + } + + visited.add(name); + ordered[name] = modules[name]; + } + + for (const name of moduleSet) { + visit(name); + } + + return ordered; +} +export function resolveEnv( + preset: Environment = "inmemory", + envs?: Partial +): T { + return { + ...getConfigs(preset), + ...envs, + } as T; +} +export function buildCustomTokenConfig( + customTokenPrivateKey?: string, + customTokenBridgePrivateKey?: string +): Record { + if (!customTokenPrivateKey || !customTokenBridgePrivateKey) { + return {}; + } + const pk = PrivateKey.fromBase58(customTokenPrivateKey); + const tokenId = TokenId.derive(pk.toPublicKey()).toString(); + return { + [tokenId]: { + bridgingContractPrivateKey: PrivateKey.fromBase58( + customTokenBridgePrivateKey + ), + tokenOwner: FungibleToken, + tokenOwnerPrivateKey: customTokenPrivateKey, + }, + }; +} +export function buildSettlementTokenConfig( + bridgePrivateKey: string, + customTokens: Record = {} +): Record { + return { + "1": { + bridgingContractPrivateKey: PrivateKey.fromBase58(bridgePrivateKey), + }, + ...customTokens, + }; +} +export function getConfigs(preset: Environment) { + switch (preset) { + case "development": + return developmentConfig; + case "sovereign": + return sovereignConfig; + case "inmemory": + default: + return inmemoryConfig; + } +} + +export function parseApiEnv(envs: ApiEnv): { + graphqlPort: number; + graphqlHost: string; + graphiqlEnabled: boolean; +} { + ensureDefined(envs, [ + "PROTOKIT_GRAPHIQL_ENABLED", + "PROTOKIT_GRAPHQL_HOST", + "PROTOKIT_GRAPHQL_PORT", + ]); + return { + graphqlPort: Number(envs.PROTOKIT_GRAPHQL_PORT), + graphqlHost: envs.PROTOKIT_GRAPHQL_HOST, + graphiqlEnabled: Boolean(envs.PROTOKIT_GRAPHIQL_ENABLED), + }; +} +export function parseCoreEnv( + envs: CoreEnv, + settlementEnabled?: boolean +): { + blockInterval: number; + settlementInterval?: number; + minaBridgeKey?: string; + customTokenKey?: string; + customTokenBridgeKey?: string; +} { + ensureDefined(envs, ["PROTOKIT_BLOCK_INTERVAL"]); + if (settlementEnabled) { + ensureDefined(envs, [ + "PROTOKIT_SETTLEMENT_INTERVAL", + "PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY", + ]); + if (envs.PROTOKIT_CUSTOM_TOKEN_PRIVATE_KEY) { + ensureDefined(envs, ["PROTOKIT_CUSTOM_TOKEN_BRIDGE_PRIVATE_KEY"]); + } + } + return { + blockInterval: Number(envs.PROTOKIT_BLOCK_INTERVAL), + settlementInterval: Number(envs.PROTOKIT_SETTLEMENT_INTERVAL), + minaBridgeKey: envs.PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY, + customTokenKey: envs.PROTOKIT_CUSTOM_TOKEN_PRIVATE_KEY, + customTokenBridgeKey: envs.PROTOKIT_CUSTOM_TOKEN_BRIDGE_PRIVATE_KEY, + }; +} +export function parseMetricsEnv(envs: MetricsEnv): { + metricsEnabled: boolean; + metricsHost?: string; + metricsPort?: number; + metricsScrapingFrequency?: number; + tracingEnabled: boolean; + tracingUrl?: string; +} { + ensureDefined(envs as Record, [ + "OPEN_TELEMETRY_METRICS_ENABLED", + "OPEN_TELEMETRY_TRACING_ENABLED", + "OPEN_TELEMETRY_TRACING_URL", + "OPEN_TELEMETRY_METRICS_HOST", + "OPEN_TELEMETRY_METRICS_PORT", + "OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY", + ]); + return { + metricsEnabled: Boolean(envs.OPEN_TELEMETRY_METRICS_ENABLED), + metricsHost: envs.OPEN_TELEMETRY_METRICS_HOST, + metricsPort: Number(envs.OPEN_TELEMETRY_METRICS_PORT), + metricsScrapingFrequency: Number( + envs.OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY + ), + tracingEnabled: Boolean(envs.OPEN_TELEMETRY_TRACING_ENABLED), + tracingUrl: envs.OPEN_TELEMETRY_TRACING_URL, + }; +} +export function parseSettlementEnv(envs: SettlementEnv): { + network: string; + graphql: string; + archive: string; + accountManager: string; + sequencerPrivateKey: string; + settlementContractPrivateKey: string; + dispatcherContractPrivateKey: string; + minaBridgeContractPrivateKey: string; +} { + ensureDefined(envs as Record, [ + "MINA_ACCOUNT_MANAGER_HOST", + "MINA_ACCOUNT_MANAGER_PORT", + "MINA_ARCHIVE_GRAPHQL_HOST", + "MINA_ARCHIVE_GRAPHQL_PORT", + "MINA_NODE_GRAPHQL_HOST", + "MINA_NODE_GRAPHQL_PORT", + "MINA_NETWORK", + "PROTOKIT_SEQUENCER_PRIVATE_KEY", + "PROTOKIT_SETTLEMENT_CONTRACT_PRIVATE_KEY", + "PROTOKIT_DISPATCHER_CONTRACT_PRIVATE_KEY", + "PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY", + ]); + + return { + network: envs.MINA_NETWORK!, + graphql: `${envs.MINA_NODE_GRAPHQL_HOST}:${envs.MINA_NODE_GRAPHQL_PORT}/graphql`, + archive: `${envs.MINA_ARCHIVE_GRAPHQL_HOST}:${envs.MINA_ARCHIVE_GRAPHQL_PORT}`, + accountManager: `${envs.MINA_ACCOUNT_MANAGER_HOST}:${envs.MINA_ACCOUNT_MANAGER_PORT}`, + sequencerPrivateKey: envs.PROTOKIT_SEQUENCER_PRIVATE_KEY!, + settlementContractPrivateKey: + envs.PROTOKIT_SETTLEMENT_CONTRACT_PRIVATE_KEY!, + dispatcherContractPrivateKey: + envs.PROTOKIT_DISPATCHER_CONTRACT_PRIVATE_KEY!, + minaBridgeContractPrivateKey: + envs.PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY!, + }; +} +export function parseIndexerEnv(envs: IndexerEnv): { + redisHost?: string; + redisPort?: number; + redisPassword?: string; + indexerDatabaseUrl?: string; + graphqlPort?: number; + graphqlHost?: string; + graphiqlEnabled?: boolean; +} { + ensureDefined(envs as Record, [ + "REDIS_HOST", + "REDIS_PORT", + "REDIS_PASSWORD", + "INDEXER_DATABASE_URL", + "PROTOKIT_INDEXER_GRAPHQL_PORT", + "PROTOKIT_INDEXER_GRAPHQL_HOST", + "PROTOKIT_INDEXER_GRAPHIQL_ENABLED", + ]); + return { + redisHost: envs.REDIS_HOST, + redisPort: envs.REDIS_PORT ? Number(envs.REDIS_PORT) : undefined, + redisPassword: envs.REDIS_PASSWORD, + indexerDatabaseUrl: envs.INDEXER_DATABASE_URL, + graphqlPort: envs.PROTOKIT_INDEXER_GRAPHQL_PORT + ? Number(envs.PROTOKIT_INDEXER_GRAPHQL_PORT) + : undefined, + graphqlHost: envs.PROTOKIT_INDEXER_GRAPHQL_HOST, + graphiqlEnabled: envs.PROTOKIT_INDEXER_GRAPHIQL_ENABLED + ? Boolean(envs.PROTOKIT_INDEXER_GRAPHIQL_ENABLED) + : undefined, + }; +} +export function parseProcessorEnv(envs: ProcessorEnv): { + processorIndexerGraphqlHost?: string; + indexerGraphqlPort?: number; + blockInterval?: number; + processorGraphqlHost?: string; + processorGraphqlPort?: number; + processorGraphiqlEnabled?: boolean; +} { + ensureDefined(envs as Record, [ + "PROTOKIT_PROCESSOR_INDEXER_GRAPHQL_HOST", + "PROTOKIT_INDEXER_GRAPHQL_PORT", + "PROTOKIT_BLOCK_INTERVAL", + "PROTOKIT_PROCESSOR_GRAPHQL_HOST", + "PROTOKIT_PROCESSOR_GRAPHQL_PORT", + "PROTOKIT_PROCESSOR_GRAPHIQL_ENABLED", + ]); + return { + processorIndexerGraphqlHost: envs.PROTOKIT_PROCESSOR_INDEXER_GRAPHQL_HOST, + indexerGraphqlPort: envs.PROTOKIT_INDEXER_GRAPHQL_PORT + ? Number(envs.PROTOKIT_INDEXER_GRAPHQL_PORT) + : undefined, + blockInterval: envs.PROTOKIT_BLOCK_INTERVAL + ? Number(envs.PROTOKIT_BLOCK_INTERVAL) + : undefined, + processorGraphqlHost: envs.PROTOKIT_PROCESSOR_GRAPHQL_HOST, + processorGraphqlPort: envs.PROTOKIT_PROCESSOR_GRAPHQL_PORT + ? Number(envs.PROTOKIT_PROCESSOR_GRAPHQL_PORT) + : undefined, + processorGraphiqlEnabled: envs.PROTOKIT_PROCESSOR_GRAPHIQL_ENABLED + ? Boolean(envs.PROTOKIT_PROCESSOR_GRAPHIQL_ENABLED) + : undefined, + }; +} +export function parseDatabaseEnv(envs: DatabaseEnv): { + redisHost?: string; + redisPort?: number; + redisPassword?: string; + databaseUrl?: string; +} { + return { + redisHost: envs.REDIS_HOST, + redisPort: envs.REDIS_PORT ? Number(envs.REDIS_PORT) : undefined, + redisPassword: envs.REDIS_PASSWORD, + databaseUrl: envs.DATABASE_URL, + }; +} +export function parseTaskQueueEnv(envs: TaskQueueEnv): { + redisHost?: string; + redisPort?: number; + redisPassword?: string; +} { + return { + redisHost: envs.REDIS_HOST, + redisPort: envs.REDIS_PORT ? Number(envs.REDIS_PORT) : undefined, + redisPassword: envs.REDIS_PASSWORD, + }; +} +export function parseDatabasePruneEnv(envs: DatabasePruneEnv): { + pruneOnStartup: boolean; +} { + return { + pruneOnStartup: + envs.PRUNE_ON_STARTUP === "true" || envs.PRUNE_ON_STARTUP === true, + }; +} +export function parseGraphqlServerEnv( + envs: GraphqlServerEnv, + type: "protokit" | "indexer" | "processor" = "protokit" +): { + graphqlPort?: number; + graphqlHost?: string; + graphiqlEnabled?: boolean; +} { + const prefix = + type === "indexer" + ? "PROTOKIT_INDEXER" + : type === "processor" + ? "PROTOKIT_PROCESSOR" + : "PROTOKIT"; + return { + graphqlPort: envs[`${prefix}_GRAPHQL_PORT`] + ? Number(envs[`${prefix}_GRAPHQL_PORT`]) + : undefined, + graphqlHost: envs[`${prefix}_GRAPHQL_HOST`], + graphiqlEnabled: envs[`${prefix}_GRAPHIQL_ENABLED`] + ? Boolean(envs[`${prefix}_GRAPHIQL_ENABLED`]) + : undefined, + }; +} +export function parseRedisEnv(envs: RedisEnv): { + redisHost?: string; + redisPort?: number; + redisPassword?: string; +} { + return { + redisHost: envs.REDIS_HOST, + redisPort: envs.REDIS_PORT ? Number(envs.REDIS_PORT) : undefined, + redisPassword: envs.REDIS_PASSWORD, + }; +} diff --git a/packages/stack/src/presets/sequencer/index.ts b/packages/stack/src/presets/sequencer/index.ts new file mode 100644 index 000000000..1fd6919fb --- /dev/null +++ b/packages/stack/src/presets/sequencer/index.ts @@ -0,0 +1,136 @@ +import { SequencerModulesRecord, Sequencer } from "@proto-kit/sequencer"; +import { ModulesConfig, RecursivePartial } from "@proto-kit/common"; +import { DefaultConfigs, DefaultModules } from "../modules"; +import { definePreset } from "../modules/utils"; + +export class DefaultSequencer { + static inmemory(options?: { + overrideModules?: Partial; + settlementEnabled?: boolean; + }) { + const modules = DefaultModules.ordered( + definePreset( + { + ...DefaultModules.database(), + ...DefaultModules.core({ + settlementEnabled: options?.settlementEnabled, + }), + ...DefaultModules.taskQueue(), + ...(options?.settlementEnabled ? DefaultModules.settlement() : {}), + }, + options?.overrideModules + ) + ); + + return Sequencer.from(modules); + } + static development(options?: { + overrideModules?: Partial; + settlementEnabled?: boolean; + }) { + const modules = DefaultModules.ordered( + definePreset( + { + // ordering of the modules matters due to dependency resolution + ...DefaultModules.database({ preset: "development" }), + ...DefaultModules.databasePrune(), + ...DefaultModules.metrics(), + ...DefaultModules.taskQueue({ preset: "development" }), + ...DefaultModules.core({ + settlementEnabled: options?.settlementEnabled, + }), + ...DefaultModules.sequencerIndexer(), + }, + options?.overrideModules + ) + ); + + return Sequencer.from(modules); + } + static sovereign(options?: { + overrideModules?: Partial; + settlementEnabled?: boolean; + }) { + const modules = DefaultModules.ordered( + definePreset( + { + // ordering of the modules matters due to dependency resolution + ...DefaultModules.database(), + ...DefaultModules.taskQueue(), + ...DefaultModules.core({ + settlementEnabled: options?.settlementEnabled, + }), + ...DefaultModules.sequencerIndexer(), + ...DefaultModules.metrics(), + ...DefaultModules.databasePrune(), + }, + options?.overrideModules + ) + ); + + return Sequencer.from(modules); + } +} +export class DefaultSequencerConfig { + static inmemory(options?: { + overrideConfig?: RecursivePartial>; + settlementEnabled?: boolean; + }) { + return { + ...DefaultConfigs.core({ settlementEnabled: options?.settlementEnabled }), + ...DefaultConfigs.database({ preset: "inmemory" }), + ...DefaultConfigs.taskQueue({ preset: "inmemory" }), + ...options?.overrideConfig, + }; + } + static development(options?: { + overrideConfig?: RecursivePartial>; + settlementEnabled?: boolean; + }) { + return { + ...DefaultConfigs.core({ + settlementEnabled: options?.settlementEnabled, + preset: "development", + }), + ...DefaultConfigs.sequencerIndexer(), + ...DefaultConfigs.metrics({ preset: "development" }), + ...DefaultConfigs.databasePrune({ preset: "development" }), + ...DefaultConfigs.taskQueue({ + preset: "development", + overrides: { + ...DefaultConfigs.redis({ + preset: "development", + overrides: { db: 1 }, + }), + }, + }), + ...DefaultConfigs.database({ preset: "development" }), + ...options?.overrideConfig, + }; + } + static sovereign(options?: { + overrideConfig?: RecursivePartial>; + settlementEnabled?: boolean; + }) { + return { + ...DefaultConfigs.core({ + settlementEnabled: options?.settlementEnabled, + preset: "sovereign", + }), + ...DefaultConfigs.sequencerIndexer(), + ...DefaultConfigs.metrics({ preset: "sovereign" }), + ...DefaultConfigs.databasePrune({ preset: "sovereign" }), + ...DefaultConfigs.taskQueue({ + preset: "sovereign", + overrides: { + ...DefaultConfigs.redis({ + preset: "sovereign", + overrides: { db: 1 }, + }), + }, + }), + ...DefaultConfigs.database({ preset: "sovereign" }), + ...options?.overrideConfig, + }; + } +} From 61c9abb73a8290e49d0a3005543dd1a4cea366ad Mon Sep 17 00:00:00 2001 From: stanlou Date: Sat, 24 Jan 2026 05:44:12 +0100 Subject: [PATCH 2/4] use default modules --- packages/processor/src/index.ts | 1 + packages/stack/package.json | 4 +- packages/stack/src/index.ts | 6 +- packages/stack/src/presets/app-chain/index.ts | 122 --- packages/stack/src/presets/config.ts | 235 +++--- packages/stack/src/presets/modules/index.ts | 779 ++++++++---------- packages/stack/src/presets/modules/types.ts | 123 ++- packages/stack/src/presets/modules/utils.ts | 369 +-------- packages/stack/src/presets/sequencer/index.ts | 136 --- 9 files changed, 533 insertions(+), 1242 deletions(-) delete mode 100644 packages/stack/src/presets/app-chain/index.ts delete mode 100644 packages/stack/src/presets/sequencer/index.ts diff --git a/packages/processor/src/index.ts b/packages/processor/src/index.ts index b6bc05ff7..918e46e03 100644 --- a/packages/processor/src/index.ts +++ b/packages/processor/src/index.ts @@ -1,6 +1,7 @@ export * from "./Processor"; export * from "./ProcessorModule"; export * from "./handlers/HandlersExecutor"; +export * from "./handlers/BasePrismaClient"; export * from "./storage/Database"; export * from "./triggers/TimedProcessorTrigger"; export * from "./indexer/BlockFetching"; diff --git a/packages/stack/package.json b/packages/stack/package.json index e983b9fe9..dc3c50ad3 100644 --- a/packages/stack/package.json +++ b/packages/stack/package.json @@ -39,7 +39,9 @@ "dependencies": { "reflect-metadata": "^0.1.13", "@prisma/client": "^5.19.1", - "mina-fungible-token": "^1.1.0" + "mina-fungible-token": "^1.1.0", + "type-graphql": "2.0.0-rc.2" + }, "gitHead": "397881ed5d8f98f5005bcd7be7f5a12b3bc6f956" } diff --git a/packages/stack/src/index.ts b/packages/stack/src/index.ts index 3c5da028c..fb31453cc 100644 --- a/packages/stack/src/index.ts +++ b/packages/stack/src/index.ts @@ -1,5 +1,5 @@ export * from "./scripts/graphql/server"; -export * from "./presets/app-chain"; -export * from "./presets/sequencer"; export * from "./presets/config"; -export * from "./presets/modules"; \ No newline at end of file +export * from "./presets/modules/types"; +export * from "./presets/modules/utils"; +export * from "./presets/modules"; diff --git a/packages/stack/src/presets/app-chain/index.ts b/packages/stack/src/presets/app-chain/index.ts deleted file mode 100644 index 48db076cc..000000000 --- a/packages/stack/src/presets/app-chain/index.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { ModulesConfig, RecursivePartial } from "@proto-kit/common"; -import { Runtime, RuntimeModulesRecord } from "@proto-kit/module"; -import { - MandatoryProtocolModulesRecord, - Protocol, - ProtocolModulesRecord, -} from "@proto-kit/protocol"; -import { - AppChain, - AppChainModulesRecord, - SequencerModulesRecord, -} from "@proto-kit/sequencer"; -import { DefaultModules, DefaultConfigs } from "../modules"; -import { DefaultSequencer, DefaultSequencerConfig } from "../sequencer"; - -export class DefaultAppChain { - static inmemory( - runtimeModules: RuntimeModulesRecord, - protocolModules: ProtocolModulesRecord & MandatoryProtocolModulesRecord, - options?: { - overrideAppChainModules?: Partial; - settlementEnabled?: boolean; - overrideSequencerModules?: Partial; - } - ) { - return AppChain.from({ - Runtime: Runtime.from(runtimeModules), - Protocol: Protocol.from(protocolModules), - Sequencer: DefaultSequencer.inmemory({ - settlementEnabled: options?.settlementEnabled, - overrideModules: options?.overrideSequencerModules, - }), - ...DefaultModules.appChainBase(), - ...options?.overrideAppChainModules, - }); - } - static development( - runtimeModules: RuntimeModulesRecord, - protocolModules: ProtocolModulesRecord & MandatoryProtocolModulesRecord, - options?: { - overrideAppChainModules?: Partial; - settlementEnabled?: boolean; - overrideSequencerModules?: Partial; - } - ) { - return AppChain.from({ - Runtime: Runtime.from(runtimeModules), - Protocol: Protocol.from(protocolModules), - Sequencer: DefaultSequencer.development({ - settlementEnabled: options?.settlementEnabled, - overrideModules: options?.overrideSequencerModules, - }), - ...DefaultModules.appChainBase(), - ...options?.overrideAppChainModules, - }); - } - static sovereign( - runtimeModules: RuntimeModulesRecord, - protocolModules: ProtocolModulesRecord & MandatoryProtocolModulesRecord, - options?: { - overrideAppChainModules?: Partial; - settlementEnabled?: boolean; - overrideSequencerModules?: Partial; - } - ) { - return AppChain.from({ - Runtime: Runtime.from(runtimeModules), - Protocol: Protocol.from(protocolModules), - Sequencer: DefaultSequencer.sovereign({ - settlementEnabled: options?.settlementEnabled, - overrideModules: options?.overrideSequencerModules, - }), - ...DefaultModules.appChainBase(), - ...options?.overrideAppChainModules, - }); - } -} - -export class DefaultAppChainConfig { - static inmemory(options?: { - overrideAppChainConfig?: RecursivePartial>; - settlementEnabled?: boolean; - overrideSequencerConfig?: RecursivePartial>; - }) { - return { - Sequencer: DefaultSequencerConfig.inmemory({ - settlementEnabled: options?.settlementEnabled, - overrideConfig: options?.overrideSequencerConfig, - }), - ...DefaultConfigs.appChainBase(), - ...options?.overrideAppChainConfig, - }; - } - static development(options?: { - overrideAppChainConfig?: RecursivePartial>; - settlementEnabled?: boolean; - overrideSequencerConfig?: RecursivePartial>; - }) { - return { - Sequencer: DefaultSequencerConfig.development({ - settlementEnabled: options?.settlementEnabled, - overrideConfig: options?.overrideSequencerConfig, - }), - ...DefaultConfigs.appChainBase(), - ...options?.overrideAppChainConfig, - }; - } - static sovereign(options?: { - overrideAppChainConfig?: RecursivePartial>; - settlementEnabled?: boolean; - overrideSequencerConfig?: RecursivePartial>; - }) { - return { - Sequencer: DefaultSequencerConfig.sovereign({ - settlementEnabled: options?.settlementEnabled, - overrideConfig: options?.overrideSequencerConfig, - }), - ...DefaultConfigs.appChainBase(), - ...options?.overrideAppChainConfig, - }; - } -} diff --git a/packages/stack/src/presets/config.ts b/packages/stack/src/presets/config.ts index 835402150..040b14f42 100644 --- a/packages/stack/src/presets/config.ts +++ b/packages/stack/src/presets/config.ts @@ -1,193 +1,184 @@ export const inmemoryConfig = { - PROTOKIT_BLOCK_INTERVAL: 5000, - PROTOKIT_GRAPHQL_PORT: 8080, - PROTOKIT_GRAPHQL_HOST: "localhost", - PROTOKIT_GRAPHIQL_ENABLED: true, + blockInterval: 5000, + graphqlHost: "localhost", + graphqlPort: 8080, + graphiqlEnabled: true, }; - export const developmentConfig = { - PROTOKIT_PROOFS_ENABLED: false, - PROTOKIT_SHOULD_ATTEMPT_DB_MIGRATION: true, - PROTOKIT_SHOULD_ATTEMPT_INDEXER_DB_MIGRATION: true, - PROTOKIT_SHOULD_ATTEMPT_PROCESSOR_DB_MIGRATION: true, - PROTOKIT_PRUNE_ON_STARTUP: false, - PROTOKIT_LOG_LEVEL: "INFO", - - PROTOKIT_BLOCK_INTERVAL: 30000, - PROTOKIT_SETTLEMENT_INTERVAL: 60000, - PROTOKIT_SETTLEMENT_ENABLED: true, - - REDIS_HOST: "localhost", - REDIS_PORT: 6379, - REDIS_PASSWORD: "password", - - DATABASE_URL: + proofsEnabled: false, + + shouldAttemptDbMigration: true, + shouldAttemptIndexerDbMigration: true, + shouldAttemptProcessorDbMigration: true, + + pruneOnStartup: false, + + blockInterval: 30000, + settlementInterval: 60000, + settlementEnabled: true, + + redisHost: "localhost", + redisPort: 6379, + redisPassword: "password", + + databaseUrl: "postgresql://admin:password@localhost:5432/protokit?schema=public", - INDEXER_DATABASE_URL: + indexerDatabaseUrl: "postgresql://admin:password@localhost:5433/protokit-indexer?schema=public", - PROCESSOR_DATABASE_URL: + processorDatabaseUrl: "postgresql://admin:password@localhost:5434/protokit-processor?schema=public", - PROTOKIT_GRAPHQL_HOST: "0.0.0.0", - PROTOKIT_GRAPHQL_PORT: 8080, - PROTOKIT_GRAPHIQL_ENABLED: true, + graphqlHost: "0.0.0.0", + graphqlPort: 8080, + graphiqlEnabled: true, - PROTOKIT_INDEXER_GRAPHQL_HOST: "0.0.0.0", - PROTOKIT_INDEXER_GRAPHQL_PORT: 8081, - PROTOKIT_INDEXER_GRAPHIQL_ENABLED: true, + indexerGraphqlHost: "0.0.0.0", + indexerGraphqlPort: 8081, + indexerGraphqlEnabled: true, - PROTOKIT_PROCESSOR_GRAPHQL_HOST: "0.0.0.0", - PROTOKIT_PROCESSOR_GRAPHQL_PORT: 8082, - PROTOKIT_PROCESSOR_GRAPHIQL_ENABLED: true, - PROTOKIT_PROCESSOR_INDEXER_GRAPHQL_HOST: "0.0.0.0", + processorGraphqlHost: "0.0.0.0", + processorGraphqlPort: 8082, + processorGraphqlEnabled: true, - MINA_NETWORK: "lightnet", - MINA_NODE_GRAPHQL_HOST: "http://localhost", - MINA_NODE_GRAPHQL_PORT: 8083, + processorIndexerGraphqlHost: "0.0.0.0", - MINA_ARCHIVE_GRAPHQL_HOST: "http://localhost", - MINA_ARCHIVE_GRAPHQL_PORT: 8085, + minaNetwork: "lightnet", + minaNodeGraphqlHost: "http://localhost", + minaNodeGraphqlPort: 8083, - MINA_ACCOUNT_MANAGER_HOST: "http://localhost", - MINA_ACCOUNT_MANAGER_PORT: 8084, - MINA_EXPLORER_PORT: 3001, + minaArchiveGraphqlHost: "http://localhost", + minaArchiveGraphqlPort: 8085, - PROTOKIT_TRANSACTION_FEE_RECIPIENT_PRIVATE_KEY: + minaAccountManagerHost: "http://localhost", + minaAccountManagerPort: 8084, + minaExplorerPort: 3001, + + transactionFeeRecipientPrivateKey: "EKEssvj33MMBCg2tcybTzL32nTKbbwFHm6yUxd3JassdhL3J5aT8", - PROTOKIT_TRANSACTION_FEE_RECIPIENT_PUBLIC_KEY: + transactionFeeRecipientPublicKey: "B62qk4sNnzZqqjHp8YQXZUV3dBpnjiNieJVnsuh7mD2bMJ9PdbskH5H", - PROTOKIT_SEQUENCER_PRIVATE_KEY: - "EKEdKhgUHMuDvwWJEg2TdCMCeiTSd9hh2HrEr6uYJfPVuwur1s43", - PROTOKIT_SEQUENCER_PUBLIC_KEY: - "B62qizW6aroTxQorJz4ywVNZom4jA6W4QPPCK3wLeyhnJHtVStUNniL", + sequencerPrivateKey: "EKEdKhgUHMuDvwWJEg2TdCMCeiTSd9hh2HrEr6uYJfPVuwur1s43", + sequencerPublicKey: "B62qizW6aroTxQorJz4ywVNZom4jA6W4QPPCK3wLeyhnJHtVStUNniL", - PROTOKIT_SETTLEMENT_CONTRACT_PRIVATE_KEY: + settlementContractPrivateKey: "EKErS9gYHZNawqKuwfMiwYYJtNptCrvca491QEvB3tz8sFsS5w66", - PROTOKIT_SETTLEMENT_CONTRACT_PUBLIC_KEY: + settlementContractPublicKey: "B62qjKhzrvDgTPXCp34ozmpFSx4sC9owZe6eDzhdGPdoiUbGPmBkHTt", - PROTOKIT_DISPATCHER_CONTRACT_PRIVATE_KEY: + dispatcherContractPrivateKey: "EKF9Ei5G9PeB5ULMh9R6P5LfWX2gs15XxPNsect1pbcbMY9vs6v7", - PROTOKIT_DISPATCHER_CONTRACT_PUBLIC_KEY: + dispatcherContractPublicKey: "B62qmAzUJ1jqcsEf2V3K1k2Ec4MLsEKnodEvvJ5uweTFSLYEUALe1zs", - PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY: + minaBridgeContractPrivateKey: "EKFKTGqWU2egLKhMgoxX8mQ21zXSE1RZYkY82mmK9F3BxdSA7E5M", - PROTOKIT_MINA_BRIDGE_CONTRACT_PUBLIC_KEY: + minaBridgeContractPublicKey: "B62qn8XRkWcaBvv6F7kvarKs4cViaKRMbTUHT8FrDXLnvxuV6n7CHsN", - PROTOKIT_CUSTOM_TOKEN_PRIVATE_KEY: - "EKFZHQSo5YdrcU7neDaNZruYHvCiNncvdZyKXuS6MDCW1fyCFKDP", + customTokenPrivateKey: "EKFZHQSo5YdrcU7neDaNZruYHvCiNncvdZyKXuS6MDCW1fyCFKDP", - PROTOKIT_CUSTOM_TOKEN_ADMIN_PRIVATE_KEY: + customTokenAdminPrivateKey: "EKENQ2QRc4gAJkZjQXU86ZS9MDm1e7HFiNN6LgRJnniHJt1WXDn1", - PROTOKIT_CUSTOM_TOKEN_BRIDGE_PRIVATE_KEY: + customTokenBridgePrivateKey: "EKENQ2QRc4gAJkZjQXU86ZS9MDm1e7HFiNN6LgRJnniHJt1WXDn1", - TEST_ACCOUNT_1_PRIVATE_KEY: + testAccount1PrivateKey: "EKF5p3wQTFd4tRBiGicRf93yXK82bcRryokC1qoazRM6wq6gMzWJ", - TEST_ACCOUNT_1_PUBLIC_KEY: + testAccount1PublicKey: "B62qkVfEwyfkm5yucHEqrRjxbyx98pgdWz82pHv7LYq9Qigs812iWZ8", - OPEN_TELEMETRY_TRACING_ENABLED: true, - OPEN_TELEMETRY_TRACING_URL: "http://localhost:4318", - - OPEN_TELEMETRY_METRICS_ENABLED: true, - OPEN_TELEMETRY_METRICS_HOST: "0.0.0.0", - OPEN_TELEMETRY_METRICS_PORT: 4320, - OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY: 10, + openTelemetryTracingEnabled: true, + openTelemetryTracingUrl: "http://localhost:4318", + openTelemetryMetricsEnabled: true, + openTelemetryMetricsHost: "0.0.0.0", + openTelemetryMetricsPort: 4320, + openTelemetryMetricsScrapingFrequency: 10, }; - export const sovereignConfig = { - PROTOKIT_BLOCK_INTERVAL: 10000, - PROTOKIT_SETTLEMENT_INTERVAL: 30000, - PROTOKIT_SETTLEMENT_ENABLED: true, + blockInterval: 10000, + settlementInterval: 30000, + settlementEnabled: true, - PROTOKIT_SHOULD_ATTEMPT_DB_MIGRATION: true, - PROTOKIT_SHOULD_ATTEMPT_INDEXER_DB_MIGRATION: true, - PROTOKIT_SHOULD_ATTEMPT_PROCESSOR_DB_MIGRATION: true, + shouldAttemptDbMigration: true, + shouldAttemptIndexerDbMigration: true, + shouldAttemptProcessorDbMigration: true, - PROTOKIT_PRUNE_ON_STARTUP: false, - PROTOKIT_LOG_LEVEL: "INFO", + pruneOnStartup: false, - REDIS_HOST: "redis", - REDIS_PORT: 6379, - REDIS_PASSWORD: "password", + redisHost: "redis", + redisPort: 6379, + redisPassword: "password", - DATABASE_URL: + databaseUrl: "postgresql://admin:password@postgres:5432/protokit?schema=public", - INDEXER_DATABASE_URL: + indexerDatabaseUrl: "postgresql://admin:password@indexer-postgres:5432/protokit-indexer?schema=public", - PROCESSOR_DATABASE_URL: + processorDatabaseUrl: "postgresql://admin:password@processor-postgres:5432/protokit-processor?schema=public", - PROTOKIT_GRAPHQL_HOST: "0.0.0.0", - PROTOKIT_GRAPHQL_PORT: 8080, - PROTOKIT_GRAPHIQL_ENABLED: true, + graphqlHost: "0.0.0.0", + graphqlPort: 8080, + graphiqlEnabled: true, - PROTOKIT_INDEXER_GRAPHQL_HOST: "0.0.0.0", - PROTOKIT_INDEXER_GRAPHQL_PORT: 8081, - PROTOKIT_INDEXER_GRAPHIQL_ENABLED: true, + indexerGraphqlHost: "0.0.0.0", + indexerGraphqlPort: 8081, + indexerGraphqlEnabled: true, - PROTOKIT_PROCESSOR_GRAPHQL_HOST: "0.0.0.0", - PROTOKIT_PROCESSOR_GRAPHQL_PORT: 8082, - PROTOKIT_PROCESSOR_GRAPHIQL_ENABLED: true, - PROTOKIT_PROCESSOR_INDEXER_GRAPHQL_HOST: "indexer", + processorGraphqlHost: "0.0.0.0", + processorGraphqlPort: 8082, + processorGraphqlEnabled: true, + processorIndexerGraphqlHost: "indexer", - MINA_NETWORK: "lightnet", - MINA_NODE_GRAPHQL_HOST: "http://lightnet", - MINA_NODE_GRAPHQL_PORT: 8080, + minaNetwork: "lightnet", + minaNodeGraphqlHost: "http://lightnet", + minaNodeGraphqlPort: 8080, - MINA_ARCHIVE_GRAPHQL_HOST: "http://lightnet", - MINA_ARCHIVE_GRAPHQL_PORT: 8282, + minaArchiveGraphqlHost: "http://lightnet", + minaArchiveGraphqlPort: 8282, - MINA_ACCOUNT_MANAGER_HOST: "http://lightnet", - MINA_ACCOUNT_MANAGER_PORT: 8084, - MINA_EXPLORER_PORT: 3001, - - PROTOKIT_TRANSACTION_FEE_RECIPIENT_PRIVATE_KEY: + minaAccountManagerHost: "http://lightnet", + minaAccountManagerPort: 8084, + minaExplorerPort: 3001, + transactionFeeRecipientPrivateKey: "EKEssvj33MMBCg2tcybTzL32nTKbbwFHm6yUxd3JassdhL3J5aT8", - PROTOKIT_TRANSACTION_FEE_RECIPIENT_PUBLIC_KEY: + transactionFeeRecipientPublicKey: "B62qk4sNnzZqqjHp8YQXZUV3dBpnjiNieJVnsuh7mD2bMJ9PdbskH5H", - PROTOKIT_SEQUENCER_PRIVATE_KEY: - "EKEdKhgUHMuDvwWJEg2TdCMCeiTSd9hh2HrEr6uYJfPVuwur1s43", - PROTOKIT_SEQUENCER_PUBLIC_KEY: - "B62qizW6aroTxQorJz4ywVNZom4jA6W4QPPCK3wLeyhnJHtVStUNniL", + sequencerPrivateKey: "EKEdKhgUHMuDvwWJEg2TdCMCeiTSd9hh2HrEr6uYJfPVuwur1s43", + sequencerPublicKey: "B62qizW6aroTxQorJz4ywVNZom4jA6W4QPPCK3wLeyhnJHtVStUNniL", - PROTOKIT_SETTLEMENT_CONTRACT_PRIVATE_KEY: + settlementContractPrivateKey: "EKErS9gYHZNawqKuwfMiwYYJtNptCrvca491QEvB3tz8sFsS5w66", - PROTOKIT_SETTLEMENT_CONTRACT_PUBLIC_KEY: + settlementContractPublicKey: "B62qjKhzrvDgTPXCp34ozmpFSx4sC9owZe6eDzhdGPdoiUbGPmBkHTt", - PROTOKIT_DISPATCHER_CONTRACT_PRIVATE_KEY: + dispatcherContractPrivateKey: "EKF9Ei5G9PeB5ULMh9R6P5LfWX2gs15XxPNsect1pbcbMY9vs6v7", - PROTOKIT_DISPATCHER_CONTRACT_PUBLIC_KEY: + dispatcherContractPublicKey: "B62qmAzUJ1jqcsEf2V3K1k2Ec4MLsEKnodEvvJ5uweTFSLYEUALe1zs", - PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY: + minaBridgeContractPrivateKey: "EKFKTGqWU2egLKhMgoxX8mQ21zXSE1RZYkY82mmK9F3BxdSA7E5M", - PROTOKIT_MINA_BRIDGE_CONTRACT_PUBLIC_KEY: + minaBridgeContractPublicKey: "B62qn8XRkWcaBvv6F7kvarKs4cViaKRMbTUHT8FrDXLnvxuV6n7CHsN", - TEST_ACCOUNT_1_PRIVATE_KEY: + testAccount1PrivateKey: "EKF5p3wQTFd4tRBiGicRf93yXK82bcRryokC1qoazRM6wq6gMzWJ", - TEST_ACCOUNT_1_PUBLIC_KEY: + testAccount1PublicKey: "B62qkVfEwyfkm5yucHEqrRjxbyx98pgdWz82pHv7LYq9Qigs812iWZ8", - - OPEN_TELEMETRY_TRACING_ENABLED: true, - OPEN_TELEMETRY_TRACING_URL: "http://otel-collector:4317", - OPEN_TELEMETRY_METRICS_ENABLED: true, - OPEN_TELEMETRY_METRICS_HOST: "0.0.0.0", - OPEN_TELEMETRY_METRICS_PORT: 4320, - OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY: 10, + openTelemetryTracingEnabled: true, + openTelemetryTracingUrl: "http://otel-collector:4317", -}; \ No newline at end of file + openTelemetryMetricsEnabled: true, + openTelemetryMetricsHost: "0.0.0.0", + openTelemetryMetricsPort: 4320, + openTelemetryMetricsScrapingFrequency: 10, +}; diff --git a/packages/stack/src/presets/modules/index.ts b/packages/stack/src/presets/modules/index.ts index 4561e14e1..d1067aadd 100644 --- a/packages/stack/src/presets/modules/index.ts +++ b/packages/stack/src/presets/modules/index.ts @@ -19,13 +19,13 @@ import { DatabasePruneModule, InMemoryDatabase, LocalTaskQueue, + AppChainModulesRecord, } from "@proto-kit/sequencer"; import { IndexerNotifier, GeneratedResolverFactoryGraphqlModule, IndexBlockTask, } from "@proto-kit/indexer"; -import { PrivateKey } from "o1js"; import { PrismaRedisDatabase } from "@proto-kit/persistance"; import { BullQueue } from "@proto-kit/deployment"; import { @@ -41,579 +41,476 @@ import { InMemoryTransactionSender, StateServiceQueryModule, } from "@proto-kit/sdk"; -import { AppChainModulesRecord } from "@proto-kit/sequencer"; +import { PrivateKey } from "o1js"; +import { NonEmptyArray } from "type-graphql"; + import { buildCustomTokenConfig, buildSettlementTokenConfig, - definePreset, - orderModulesByDependencies, - parseApiEnv, - parseCoreEnv, - parseMetricsEnv, - parseSettlementEnv, - parseIndexerEnv, - parseProcessorEnv, - parseDatabaseEnv, - parseDatabasePruneEnv, - parseGraphqlServerEnv, - parseRedisEnv, resolveEnv, } from "./utils"; -import { NonEmptyArray } from "type-graphql"; import { Environment, - ModuleOverrides, - ApiEnv, - ConfigOverrides, CoreEnv, MetricsEnv, IndexerEnv, ProcessorEnv, SettlementEnv, + RedisEnv, DatabaseEnv, - TaskQueueEnv, - DatabasePruneEnv, + RedisTaskQueueEnv, GraphqlServerEnv, - RedisEnv, } from "./types"; export class DefaultModules { - static api(options?: { - overrides?: ModuleOverrides; - }): SequencerModulesRecord { - return definePreset( - { - GraphqlServer, - Graphql: GraphqlSequencerModule.from(VanillaGraphqlModules.with({})), - }, - options?.overrides - ); + static api() { + return { + GraphqlServer, + Graphql: GraphqlSequencerModule.from(VanillaGraphqlModules.with({})), + } satisfies SequencerModulesRecord; } - static core(options?: { - overrides?: ModuleOverrides; - settlementEnabled?: boolean; - }): SequencerModulesRecord { - return definePreset( - { - ...DefaultModules.api(), - Mempool: PrivateMempool, - BlockProducerModule, - BlockTrigger: TimedBlockTrigger, - SequencerStartupModule, - LocalTaskWorkerModule: LocalTaskWorkerModule.from( - VanillaTaskWorkerModules.withoutSettlement() - ), - ...(options?.settlementEnabled ? DefaultModules.settlement() : {}), - }, - options?.overrides - ); + + static core(options?: { settlementEnabled?: boolean }) { + const settlementEnabled = options?.settlementEnabled ?? false; + return { + ...(settlementEnabled ? DefaultModules.settlement() : {}), + ...DefaultModules.api(), + Mempool: PrivateMempool, + BlockProducerModule, + BlockTrigger: TimedBlockTrigger, + SequencerStartupModule, + LocalTaskWorkerModule: LocalTaskWorkerModule.from( + VanillaTaskWorkerModules.withoutSettlement() + ), + } satisfies SequencerModulesRecord; } - static metrics(options?: { - overrides?: ModuleOverrides; - }): SequencerModulesRecord { - return definePreset( - { - OpenTelemetryServer, - }, - options?.overrides - ); + + static metrics() { + return { + OpenTelemetryServer, + } satisfies SequencerModulesRecord; } - static settlement(options?: { - overrides?: ModuleOverrides; - }): SequencerModulesRecord { - return definePreset( - { - BaseLayer: MinaBaseLayer, - FeeStrategy: ConstantFeeStrategy, - BatchProducerModule, - SettlementModule, - LocalTaskWorkerModule: LocalTaskWorkerModule.from( - VanillaTaskWorkerModules.allTasks() - ), - }, - options?.overrides - ); + + static settlement() { + return { + BaseLayer: MinaBaseLayer, + FeeStrategy: ConstantFeeStrategy, + BatchProducerModule, + SettlementModule, + LocalTaskWorkerModule: LocalTaskWorkerModule.from( + VanillaTaskWorkerModules.allTasks() + ), + } satisfies SequencerModulesRecord; } - static sequencerIndexer(options?: { - overrides?: ModuleOverrides; - }): SequencerModulesRecord { - return definePreset( - { - IndexerNotifier, - }, - options?.overrides - ); + + static sequencerIndexer() { + return { + IndexerNotifier, + } satisfies SequencerModulesRecord; } - static indexer(options?: { overrides?: ModuleOverrides }) { - return definePreset( - { - Database: PrismaRedisDatabase, - TaskQueue: BullQueue, - TaskWorker: LocalTaskWorkerModule.from({ - IndexBlockTask, - }), - GraphqlServer, - Graphql: GraphqlSequencerModule.from({ - GeneratedResolverFactory: GeneratedResolverFactoryGraphqlModule, - }), - }, - options?.overrides - ); + + static indexer() { + return { + Database: PrismaRedisDatabase, + TaskQueue: BullQueue, + TaskWorker: LocalTaskWorkerModule.from({ + IndexBlockTask, + }), + GraphqlServer, + Graphql: GraphqlSequencerModule.from({ + GeneratedResolverFactory: GeneratedResolverFactoryGraphqlModule, + }), + } satisfies SequencerModulesRecord; } + static processor( resolvers: NonEmptyArray, - handlers: HandlersRecord, - options?: { overrides?: ModuleOverrides } + handlers: HandlersRecord ) { - return definePreset( - { - GraphqlServer, - GraphqlSequencerModule: GraphqlSequencerModule.from({ - ResolverFactory: ResolverFactoryGraphqlModule.from(resolvers), - }), - HandlersExecutor: HandlersExecutor.from(handlers), - BlockFetching, - Trigger: TimedProcessorTrigger, - }, - options?.overrides - ); + return { + GraphqlServer, + GraphqlSequencerModule: GraphqlSequencerModule.from({ + ResolverFactory: ResolverFactoryGraphqlModule.from(resolvers), + }), + HandlersExecutor: HandlersExecutor.from(handlers), + BlockFetching, + Trigger: TimedProcessorTrigger, + } satisfies SequencerModulesRecord; } - static database(options?: { - overrides?: ModuleOverrides; - preset?: Environment; - }): SequencerModulesRecord { - const preset = options?.preset ?? "inmemory"; - return definePreset( - { - Database: - preset === "inmemory" ? InMemoryDatabase : PrismaRedisDatabase, - }, - options?.overrides - ); + static inMemoryDatabase() { + return { + Database: InMemoryDatabase, + } satisfies SequencerModulesRecord; } - static taskQueue(options?: { - overrides?: ModuleOverrides; - preset?: Environment; - }): SequencerModulesRecord { - const preset = options?.preset ?? "inmemory"; - return definePreset( - { - TaskQueue: preset === "inmemory" ? LocalTaskQueue : BullQueue, - }, - options?.overrides - ); + + static PrismaRedisDatabase() { + return { + Database: PrismaRedisDatabase, + DatabasePruneModule, + } satisfies SequencerModulesRecord; } - static databasePrune(options?: { - overrides?: ModuleOverrides; - }): SequencerModulesRecord { - return definePreset( - { - DatabasePruneModule, - }, - options?.overrides - ); + + static localTaskQueue() { + return { + TaskQueue: LocalTaskQueue, + } satisfies SequencerModulesRecord; } - static worker(options?: { - overrides?: ModuleOverrides; - }): SequencerModulesRecord { - return definePreset( - { - TaskQueue: BullQueue, - LocalTaskWorkerModule: LocalTaskWorkerModule.from( - VanillaTaskWorkerModules.allTasks() - ), - }, - options?.overrides - ); + + static RedisTaskQueue() { + return { + TaskQueue: BullQueue, + } satisfies SequencerModulesRecord; } - static appChainBase(options?: { - overrides?: Partial; - }): AppChainModulesRecord { - return definePreset( - { - TransactionSender: InMemoryTransactionSender, - QueryTransportModule: StateServiceQueryModule, - NetworkStateTransportModule: BlockStorageNetworkStateModule, - }, - options?.overrides - ) as AppChainModulesRecord; + + static worker() { + return { + TaskQueue: BullQueue, + LocalTaskWorkerModule: LocalTaskWorkerModule.from( + VanillaTaskWorkerModules.allTasks() + ), + } satisfies SequencerModulesRecord; } - static settlementScript(options?: { - overrides?: ModuleOverrides; - }): SequencerModulesRecord { - return definePreset( - { - ...DefaultModules.settlement(), - Mempool: PrivateMempool, - TaskQueue: LocalTaskQueue, - SequencerStartupModule, - }, - options?.overrides - ); + + static appChainBase() { + return { + TransactionSender: InMemoryTransactionSender, + QueryTransportModule: StateServiceQueryModule, + NetworkStateTransportModule: BlockStorageNetworkStateModule, + } satisfies AppChainModulesRecord; } - static ordered(modules: any) { - return orderModulesByDependencies(modules); + + static settlementScript() { + return { + ...DefaultModules.settlement(), + Mempool: PrivateMempool, + TaskQueue: LocalTaskQueue, + SequencerStartupModule, + } satisfies SequencerModulesRecord; } } export class DefaultConfigs { static api(options?: { preset?: Environment; - envs?: Partial; - overrides?: ConfigOverrides; - }): ConfigOverrides { - return definePreset( - { - Graphql: VanillaGraphqlModules.defaultConfig(), - GraphqlServer: DefaultConfigs.graphqlServer({ - type: "protokit", - preset: options?.preset, - envs: options?.envs, - }), - }, - options?.overrides - ); + overrides?: Partial; + }) { + return { + Graphql: VanillaGraphqlModules.defaultConfig(), + GraphqlServer: DefaultConfigs.graphqlServer({ + preset: options?.preset, + overrides: options?.overrides, + }), + }; } + static core(options?: { preset?: Environment; - envs?: Partial & Partial & Partial; - overrides?: ConfigOverrides; + overrides?: Partial & + Partial & + Partial; settlementEnabled?: boolean; - }): ConfigOverrides { - const config = resolveEnv(options?.preset, options?.envs); - const parsed = parseCoreEnv( - { ...config, ...options?.envs }, - options?.settlementEnabled - ); + }) { + const settlementEnabled = options?.settlementEnabled ?? false; + const config = resolveEnv(options?.preset, options?.overrides); const apiConfig = DefaultConfigs.api({ preset: options?.preset, - envs: options?.envs, + overrides: options?.overrides, }); - const settlementConfig = options?.settlementEnabled + const settlementConfig = settlementEnabled ? DefaultConfigs.settlement({ preset: options?.preset, - envs: options?.envs, + overrides: options?.overrides, }) : {}; const blockTriggerConfig = { - blockInterval: parsed.blockInterval, + blockInterval: config.blockInterval, produceEmptyBlocks: true, - ...(options?.settlementEnabled + ...(settlementEnabled ? { - settlementInterval: parsed.settlementInterval, + settlementInterval: config.settlementInterval, settlementTokenConfig: buildSettlementTokenConfig( - parsed.minaBridgeKey!, + config.minaBridgeContractPrivateKey!, buildCustomTokenConfig( - parsed.customTokenKey, - parsed.customTokenBridgeKey + config.customTokenPrivateKey, + config.customTokenBridgePrivateKey ) ), } : { settlementTokenConfig: {} }), }; - return definePreset( - { - ...apiConfig, - Mempool: {}, - BlockProducerModule: {}, - BlockTrigger: blockTriggerConfig, - SequencerStartupModule: {}, - LocalTaskWorkerModule: VanillaGraphqlModules.defaultConfig(), - ...settlementConfig, - }, - options?.overrides - ); + return { + ...apiConfig, + Mempool: {}, + BlockProducerModule: {}, + BlockTrigger: blockTriggerConfig, + SequencerStartupModule: {}, + LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + ...settlementConfig, + }; } + static metrics(options?: { preset?: Environment; - envs?: MetricsEnv; - overrides?: ConfigOverrides; - }): ConfigOverrides { - const configs = resolveEnv(options?.preset, options?.envs); - const parsed = parseMetricsEnv(configs); - return definePreset( - { - OpenTelemetryServer: { - metrics: { - enabled: parsed.metricsEnabled, - prometheus: { - host: parsed.metricsHost, - port: parsed.metricsPort, - appendTimestamp: true, - }, - nodeScrapeInterval: parsed.metricsScrapingFrequency, + overrides?: Partial; + }) { + const config = resolveEnv(options?.preset, options?.overrides); + return { + OpenTelemetryServer: { + metrics: { + enabled: config.metricsEnabled, + prometheus: { + host: config.metricsHost, + port: config.metricsPort, + appendTimestamp: true, }, - tracing: { - enabled: parsed.tracingEnabled, - otlp: { - url: parsed.tracingUrl, - }, + nodeScrapeInterval: config.metricsScrapingFrequency, + }, + tracing: { + enabled: config.tracingEnabled, + otlp: { + url: config.tracingUrl, }, }, }, - options?.overrides - ); + }; } - static sequencerIndexer(options?: { - overrides?: ConfigOverrides; - }): ConfigOverrides { - return definePreset({ IndexerNotifier: {} }, options?.overrides); + + static sequencerIndexer() { + return { IndexerNotifier: {} }; } + static indexer(options?: { preset?: Environment; - envs?: Partial; - overrides?: ConfigOverrides; - }): ConfigOverrides { - const config = resolveEnv(options?.preset, options?.envs); - const parsed = parseIndexerEnv(config); - const redisConfig = DefaultConfigs.redis({ + overrides?: Partial; + }) { + const config = resolveEnv(options?.preset, options?.overrides); + const taskQueueConfig = DefaultConfigs.redisTaskQueue({ preset: options?.preset, - envs: options?.envs, + overrides: options?.overrides, }); - const databaseConfig = DefaultConfigs.database({ + const databaseConfig = DefaultConfigs.prismaRedisDatabase({ preset: options?.preset, - envs: options?.envs, + overrides: { + databaseUrl: config.indexerDatabaseUrl, + ...options?.overrides, + }, }); const graphqlServerConfig = DefaultConfigs.graphqlServer({ - type: "indexer", preset: options?.preset, - envs: options?.envs, + overrides: { + graphqlHost: config.indexerGraphqlHost, + graphqlPort: config.indexerGraphqlPort, + graphiqlEnabled: config.indexerGraphqlEnabled, + ...options?.overrides, + }, }); - return definePreset( - { - ...databaseConfig, - TaskQueue: redisConfig.TaskQueue, - TaskWorker: { - IndexBlockTask: {}, - }, - ...graphqlServerConfig, - Graphql: { - GeneratedResolverFactory: {}, - }, + return { + ...databaseConfig, + ...taskQueueConfig, + TaskWorker: { + IndexBlockTask: {}, }, - options?.overrides - ); + ...graphqlServerConfig, + Graphql: { + GeneratedResolverFactory: {}, + }, + }; } + static processor(options?: { preset?: Environment; - envs?: Partial; - overrides?: ConfigOverrides; - }): ConfigOverrides { - const config = resolveEnv(options?.preset, options?.envs); - const parsed = parseProcessorEnv(config); + overrides?: Partial; + }) { + const config = resolveEnv( + options?.preset, + options?.overrides + ); const graphqlServerConfig = DefaultConfigs.graphqlServer({ - type: "processor", preset: options?.preset, - envs: options?.envs, + overrides: { + graphqlHost: config.processorGraphqlHost, + graphqlPort: config.processorGraphqlPort, + graphiqlEnabled: config.processorGraphqlEnabled, + ...options?.overrides, + }, }); - return definePreset( - { - HandlersExecutor: {}, - BlockFetching: { - url: `http://${parsed.processorIndexerGraphqlHost}:${parsed.indexerGraphqlPort}`, - }, - Trigger: { - interval: (parsed.blockInterval ?? 5000) / 5, - }, - ...graphqlServerConfig, - GraphqlSequencerModule: { - ResolverFactory: {}, - }, + return { + HandlersExecutor: {}, + BlockFetching: { + url: `http://${config.processorIndexerGraphqlHost}:${config.indexerGraphqlPort}`, }, - options?.overrides - ); + Trigger: { + interval: Number(config.blockInterval) / 5, + }, + ...graphqlServerConfig, + GraphqlSequencerModule: { + ResolverFactory: {}, + }, + }; } + static settlement(options?: { preset?: Environment; - envs?: Partial; - overrides?: ConfigOverrides; - }): ConfigOverrides { - const config = resolveEnv(options?.preset, options?.envs); - const parsed = parseSettlementEnv(config); - - return definePreset( - { - BaseLayer: { - network: { - type: parsed.network, - graphql: parsed.graphql, - archive: parsed.archive, - accountManager: parsed.accountManager, - }, + overrides?: Partial; + }) { + const config = resolveEnv( + options?.preset, + options?.overrides + ); + + return { + BaseLayer: { + network: { + type: "lightnet" as const, + graphql: config.minaNodeGraphqlHost, + archive: config.minaArchiveGraphqlHost, + accountManager: config.minaAccountManagerHost, }, - SettlementModule: { - feepayer: PrivateKey.fromBase58(parsed.sequencerPrivateKey), - keys: { - settlement: PrivateKey.fromBase58( - parsed.settlementContractPrivateKey - ), - dispatch: PrivateKey.fromBase58( - parsed.dispatcherContractPrivateKey - ), - minaBridge: PrivateKey.fromBase58( - parsed.minaBridgeContractPrivateKey - ), - }, + }, + SettlementModule: { + feepayer: PrivateKey.fromBase58(config.sequencerPrivateKey), + keys: { + settlement: PrivateKey.fromBase58( + config.settlementContractPrivateKey + ), + dispatch: PrivateKey.fromBase58(config.dispatcherContractPrivateKey), + minaBridge: PrivateKey.fromBase58( + config.minaBridgeContractPrivateKey + ), }, - FeeStrategy: {}, - BatchProducerModule: {}, }, - options?.overrides - ); + FeeStrategy: {}, + BatchProducerModule: {}, + LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + }; + } + + static inMemoryDatabase() { + return { Database: {} }; } - static database(options?: { + + static prismaRedisDatabase(options?: { preset?: Environment; - envs?: Partial; - overrides?: ConfigOverrides; - }): ConfigOverrides { - const preset = options?.preset ?? "inmemory"; - if (preset === "inmemory") { - return { Database: definePreset({}, options?.overrides) }; - } - const config = resolveEnv(options?.preset, options?.envs); - const parsed = parseDatabaseEnv(config); + overrides?: Partial; + }) { + const preset = options?.preset ?? "development"; + const config = resolveEnv(preset, options?.overrides); const redisConfig = DefaultConfigs.redis({ - preset: options?.preset, - envs: options?.envs, + preset, + overrides: options?.overrides, }); return { - Database: definePreset( - { - ...redisConfig, - prisma: { - connection: parsed.databaseUrl, - }, + Database: { + ...redisConfig, + prisma: { + connection: config.databaseUrl, }, - options?.overrides - ), + }, + DatabasePruneModule: { + pruneOnStartup: config.pruneOnStartup, + }, }; } - static taskQueue(options?: { - preset?: Environment; - envs?: Partial; - overrides?: ConfigOverrides; - }): ConfigOverrides { - const preset = options?.preset ?? "inmemory"; - if (preset === "inmemory") { - return { - TaskQueue: definePreset({}, options?.overrides), - }; - } - const redisConfig = DefaultConfigs.redis({ - preset: options?.preset, - envs: options?.envs, - }); - return { TaskQueue: definePreset(redisConfig, options?.overrides) }; + static localTaskQueue() { + return { + TaskQueue: {}, + }; } - static databasePrune(options?: { + + static redisTaskQueue(options?: { preset?: Environment; - envs?: Partial; - overrides?: ConfigOverrides; - }): ConfigOverrides { - const config = resolveEnv(options?.preset, options?.envs); - const parsed = parseDatabasePruneEnv(config); + overrides?: Partial; + }) { + const config = resolveEnv( + options?.preset, + options?.overrides + ); return { - DatabasePruneModule: definePreset( - { - pruneOnStartup: parsed.pruneOnStartup, + TaskQueue: { + redis: { + host: config.redisHost, + port: config.redisPort, + password: config.redisPassword, + db: config.redisDb, }, - options?.overrides - ), + retryAttempts: config.retryAttempts, + }, }; } + static graphqlServer(options?: { preset?: Environment; - envs?: Partial; - overrides?: ConfigOverrides; - type?: "indexer" | "processor" | "protokit"; - }): ConfigOverrides { - const config = resolveEnv(options?.preset, options?.envs); - const parsed = parseGraphqlServerEnv(config, options?.type); - - return definePreset( - { - port: parsed.graphqlPort, - host: parsed.graphqlHost, - graphiql: parsed.graphiqlEnabled, - }, + overrides?: Partial; + }) { + const config = resolveEnv( + options?.preset, options?.overrides ); + + return { + port: config.graphqlPort, + host: config.graphqlHost, + graphiql: config.graphiqlEnabled, + }; } + static redis(options?: { preset?: Environment; - envs?: Partial; - overrides?: ConfigOverrides; - }): ConfigOverrides { - const config = resolveEnv(options?.preset, options?.envs); - const parsed = parseRedisEnv(config); + overrides?: Partial; + }) { + const config = resolveEnv(options?.preset, options?.overrides); return { - redis: definePreset( - { - host: parsed.redisHost, - port: parsed.redisPort, - password: parsed.redisPassword, - }, - options?.overrides - ), + redis: { + host: config.redisHost, + port: config.redisPort, + password: config.redisPassword, + }, }; } - static appChainBase(options?: { - overrides?: ConfigOverrides; - }): ConfigOverrides { - return definePreset( - { - QueryTransportModule: {}, - NetworkStateTransportModule: {}, - TransactionSender: {}, - }, - options?.overrides - ); + + static appChainBase() { + return { + QueryTransportModule: {}, + NetworkStateTransportModule: {}, + TransactionSender: {}, + }; } + static worker(options?: { preset?: Environment; - envs?: Partial; - overrides?: ConfigOverrides; - }): ConfigOverrides { - const redisConfig = DefaultConfigs.redis({ + overrides?: Partial; + }) { + const taskQueueConfig = DefaultConfigs.redisTaskQueue({ preset: options?.preset, - envs: options?.envs, - overrides: { - db: 1, - }, + overrides: options?.overrides, }); - return definePreset( - { - TaskQueue: redisConfig, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), - }, - options?.overrides - ); + return { + ...taskQueueConfig, + LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + }; } + static settlementScript(options?: { preset?: Environment; - envs?: Partial; - overrides?: ConfigOverrides; - }): ConfigOverrides { + overrides?: Partial; + }) { const settlementConfig = DefaultConfigs.settlement({ preset: options?.preset, - envs: options?.envs, + overrides: options?.overrides, }); - return definePreset( - { - ...settlementConfig, - SequencerStartupModule: {}, - TaskQueue: { - simulatedDuration: 0, - }, - Mempool: {}, + return { + ...settlementConfig, + SequencerStartupModule: {}, + TaskQueue: { + simulatedDuration: 0, }, - options?.overrides - ); + Mempool: {}, + }; } } diff --git a/packages/stack/src/presets/modules/types.ts b/packages/stack/src/presets/modules/types.ts index 712511168..65efe1603 100644 --- a/packages/stack/src/presets/modules/types.ts +++ b/packages/stack/src/presets/modules/types.ts @@ -1,86 +1,63 @@ -import { RecursivePartial, ModulesConfig } from "@proto-kit/common"; -import { SequencerModulesRecord } from "@proto-kit/sequencer"; - -export type ModuleOverrides = Partial; -export type ConfigOverrides = RecursivePartial>; export type Environment = "inmemory" | "development" | "sovereign"; -export type ApiEnv = { - PROTOKIT_GRAPHQL_PORT: number | string; - PROTOKIT_GRAPHQL_HOST: string; - PROTOKIT_GRAPHIQL_ENABLED: boolean | string; + +export type GraphqlServerEnv = { + graphqlPort: number; + graphqlHost: string; + graphiqlEnabled: boolean; }; export type CoreEnv = { - PROTOKIT_BLOCK_INTERVAL: number | string; - PROTOKIT_SETTLEMENT_INTERVAL?: number | string; - PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY?: string; - PROTOKIT_CUSTOM_TOKEN_PRIVATE_KEY?: string; - PROTOKIT_CUSTOM_TOKEN_BRIDGE_PRIVATE_KEY?: string; + blockInterval: number; + settlementInterval?: number; + minaBridgeContractPrivateKey?: string; + customTokenPrivateKey?: string; + customTokenBridgePrivateKey?: string; }; export type MetricsEnv = { - OPEN_TELEMETRY_METRICS_ENABLED: boolean | string; - OPEN_TELEMETRY_METRICS_HOST: string; - OPEN_TELEMETRY_METRICS_PORT: number | string; - OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY: number | string; - OPEN_TELEMETRY_TRACING_ENABLED: boolean | string; - OPEN_TELEMETRY_TRACING_URL: string; + metricsEnabled: boolean; + metricsHost: string; + metricsPort: number; + metricsScrapingFrequency: number; + tracingEnabled: boolean; + tracingUrl: string; }; export type SettlementEnv = { - MINA_NETWORK: string; - MINA_NODE_GRAPHQL_HOST: string; - MINA_NODE_GRAPHQL_PORT: number | string; - MINA_ARCHIVE_GRAPHQL_HOST: string; - MINA_ARCHIVE_GRAPHQL_PORT: number | string; - MINA_ACCOUNT_MANAGER_HOST: string; - MINA_ACCOUNT_MANAGER_PORT: number | string; - PROTOKIT_SEQUENCER_PRIVATE_KEY: string; - PROTOKIT_SETTLEMENT_CONTRACT_PRIVATE_KEY: string; - PROTOKIT_DISPATCHER_CONTRACT_PRIVATE_KEY: string; - PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY: string; -}; -export type IndexerEnv = { - REDIS_HOST: string; - REDIS_PORT: number | string; - REDIS_PASSWORD: string; - INDEXER_DATABASE_URL: string; - PROTOKIT_INDEXER_GRAPHQL_PORT: number | string; - PROTOKIT_INDEXER_GRAPHQL_HOST: string; - PROTOKIT_INDEXER_GRAPHIQL_ENABLED: boolean | string; + minaNetwork: string; + minaNodeGraphqlHost: string; + minaNodeGraphqlPort: number; + minaArchiveGraphqlHost: string; + minaArchiveGraphqlPort: number; + minaAccountManagerHost: string; + minaAccountManagerPort: number; + sequencerPrivateKey: string; + settlementContractPrivateKey: string; + dispatcherContractPrivateKey: string; + minaBridgeContractPrivateKey: string; +}; +export type IndexerEnv = RedisTaskQueueEnv & { + indexerDatabaseUrl: string; + indexerGraphqlHost: string; + indexerGraphqlPort: number; + indexerGraphqlEnabled: boolean; + pruneOnStartup?: boolean; }; export type ProcessorEnv = { - PROTOKIT_PROCESSOR_INDEXER_GRAPHQL_HOST: string; - PROTOKIT_INDEXER_GRAPHQL_PORT: number | string; - PROTOKIT_BLOCK_INTERVAL: number | string; - PROTOKIT_PROCESSOR_GRAPHQL_HOST: string; - PROTOKIT_PROCESSOR_GRAPHQL_PORT: number | string; - PROTOKIT_PROCESSOR_GRAPHIQL_ENABLED: boolean | string; -}; -export type DatabaseEnv = { - REDIS_HOST: string; - REDIS_PORT: number | string; - REDIS_PASSWORD: string; - DATABASE_URL: string; + processorIndexerGraphqlHost: string; + indexerGraphqlPort: number; + blockInterval: number; + processorGraphqlHost: string; + processorGraphqlPort: number; + processorGraphqlEnabled: boolean; }; -export type TaskQueueEnv = { - REDIS_HOST: string; - REDIS_PORT: number | string; - REDIS_PASSWORD: string; -}; -export type DatabasePruneEnv = { - PRUNE_ON_STARTUP?: boolean | string; -}; -export type GraphqlServerEnv = { - PROTOKIT_GRAPHQL_PORT?: number | string; - PROTOKIT_GRAPHQL_HOST?: string; - PROTOKIT_GRAPHIQL_ENABLED?: boolean | string; - PROTOKIT_INDEXER_GRAPHQL_HOST?: string; - PROTOKIT_INDEXER_GRAPHQL_PORT?: number | string; - PROTOKIT_INDEXER_GRAPHIQL_ENABLED?: boolean | string; - PROTOKIT_PROCESSOR_GRAPHQL_HOST?: string; - PROTOKIT_PROCESSOR_GRAPHQL_PORT?: number | string; - PROTOKIT_PROCESSOR_GRAPHIQL_ENABLED?: boolean | string; +export type DatabaseEnv = RedisEnv & { + databaseUrl: string; + pruneOnStartup?: boolean; }; export type RedisEnv = { - REDIS_HOST: string; - REDIS_PORT: number | string; - REDIS_PASSWORD: string; + redisHost: string; + redisPort: number; + redisPassword: string; +}; +export type RedisTaskQueueEnv = RedisEnv & { + redisDb?: number; + retryAttempts?: number; }; diff --git a/packages/stack/src/presets/modules/utils.ts b/packages/stack/src/presets/modules/utils.ts index 679b35165..ebe16616f 100644 --- a/packages/stack/src/presets/modules/utils.ts +++ b/packages/stack/src/presets/modules/utils.ts @@ -1,106 +1,40 @@ import { PrivateKey, TokenId } from "o1js"; -import { developmentConfig, inmemoryConfig, sovereignConfig } from "../config"; import { FungibleToken } from "mina-fungible-token"; -import { assertDefined } from "@proto-kit/common"; -import { - ApiEnv, - CoreEnv, - DatabaseEnv, - DatabasePruneEnv, - Environment, - GraphqlServerEnv, - IndexerEnv, - MetricsEnv, - ProcessorEnv, - RedisEnv, - SettlementEnv, - TaskQueueEnv, -} from "./types"; - -function ensureDefined(obj: Record, keys: string[]) { - keys.forEach((k) => assertDefined(obj[k], `${k} is required`)); -} -export function definePreset( - base: T, - overrides?: Partial -): T { - return { - ...base, - ...overrides, - }; -} -const MODULE_DEPENDENCIES: Record = { - Database: [], - TaskQueue: [], - OpenTelemetryServer: [], - BaseLayer: [], - FeeStrategy: [], - - Protocol: [], - Mempool: ["Database"], - BlockProducerModule: ["Database"], - - LocalTaskWorkerModule: ["TaskQueue"], - TaskWorker: ["TaskQueue"], - SequencerStartupModule: ["Database"], - BatchProducerModule: ["Database"], - BlockTrigger: ["BlockProducerModule", "BatchProducerModule"], - - SettlementModule: ["Database", "BaseLayer", "FeeStrategy"], - DatabasePruneModule: ["Database"], - - Graphql: [], - GraphqlServer: [], - - IndexBlockTask: ["Database", "TaskQueue"], - IndexerNotifier: ["Database", "TaskQueue"], - GeneratedResolverFactory: [], - - BlockFetching: [], - HandlersExecutor: [], - Trigger: ["BlockFetching", "HandlersExecutor"], - ResolverFactory: [], -}; -export function orderModulesByDependencies( - modules: Record -): Record { - const moduleSet = new Set(Object.keys(modules)); - const ordered: Record = {}; - const visited = new Set(); - - function visit(name: string) { - if (!moduleSet.has(name) || visited.has(name)) return; - - const deps = MODULE_DEPENDENCIES[name] ?? []; - for (const dep of deps) { - visit(dep); - } +import { developmentConfig, inmemoryConfig, sovereignConfig } from "../config"; - visited.add(name); - ordered[name] = modules[name]; - } +import { Environment } from "./types"; - for (const name of moduleSet) { - visit(name); +export function getConfigs(preset: Environment) { + switch (preset) { + case "development": + return developmentConfig; + case "sovereign": + return sovereignConfig; + case "inmemory": + default: + return inmemoryConfig; } - - return ordered; } export function resolveEnv( preset: Environment = "inmemory", - envs?: Partial + envs?: Partial | undefined ): T { - return { - ...getConfigs(preset), - ...envs, - } as T; + const config = getConfigs(preset); + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + if (!envs) return config as T; + const resolved = { ...config, ...envs } satisfies Partial; + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + return resolved as T; } export function buildCustomTokenConfig( customTokenPrivateKey?: string, customTokenBridgePrivateKey?: string -): Record { - if (!customTokenPrivateKey || !customTokenBridgePrivateKey) { +) { + if ( + customTokenPrivateKey === undefined || + customTokenBridgePrivateKey === undefined + ) { return {}; } const pk = PrivateKey.fromBase58(customTokenPrivateKey); @@ -117,8 +51,8 @@ export function buildCustomTokenConfig( } export function buildSettlementTokenConfig( bridgePrivateKey: string, - customTokens: Record = {} -): Record { + customTokens: Record = {} +) { return { "1": { bridgingContractPrivateKey: PrivateKey.fromBase58(bridgePrivateKey), @@ -126,256 +60,3 @@ export function buildSettlementTokenConfig( ...customTokens, }; } -export function getConfigs(preset: Environment) { - switch (preset) { - case "development": - return developmentConfig; - case "sovereign": - return sovereignConfig; - case "inmemory": - default: - return inmemoryConfig; - } -} - -export function parseApiEnv(envs: ApiEnv): { - graphqlPort: number; - graphqlHost: string; - graphiqlEnabled: boolean; -} { - ensureDefined(envs, [ - "PROTOKIT_GRAPHIQL_ENABLED", - "PROTOKIT_GRAPHQL_HOST", - "PROTOKIT_GRAPHQL_PORT", - ]); - return { - graphqlPort: Number(envs.PROTOKIT_GRAPHQL_PORT), - graphqlHost: envs.PROTOKIT_GRAPHQL_HOST, - graphiqlEnabled: Boolean(envs.PROTOKIT_GRAPHIQL_ENABLED), - }; -} -export function parseCoreEnv( - envs: CoreEnv, - settlementEnabled?: boolean -): { - blockInterval: number; - settlementInterval?: number; - minaBridgeKey?: string; - customTokenKey?: string; - customTokenBridgeKey?: string; -} { - ensureDefined(envs, ["PROTOKIT_BLOCK_INTERVAL"]); - if (settlementEnabled) { - ensureDefined(envs, [ - "PROTOKIT_SETTLEMENT_INTERVAL", - "PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY", - ]); - if (envs.PROTOKIT_CUSTOM_TOKEN_PRIVATE_KEY) { - ensureDefined(envs, ["PROTOKIT_CUSTOM_TOKEN_BRIDGE_PRIVATE_KEY"]); - } - } - return { - blockInterval: Number(envs.PROTOKIT_BLOCK_INTERVAL), - settlementInterval: Number(envs.PROTOKIT_SETTLEMENT_INTERVAL), - minaBridgeKey: envs.PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY, - customTokenKey: envs.PROTOKIT_CUSTOM_TOKEN_PRIVATE_KEY, - customTokenBridgeKey: envs.PROTOKIT_CUSTOM_TOKEN_BRIDGE_PRIVATE_KEY, - }; -} -export function parseMetricsEnv(envs: MetricsEnv): { - metricsEnabled: boolean; - metricsHost?: string; - metricsPort?: number; - metricsScrapingFrequency?: number; - tracingEnabled: boolean; - tracingUrl?: string; -} { - ensureDefined(envs as Record, [ - "OPEN_TELEMETRY_METRICS_ENABLED", - "OPEN_TELEMETRY_TRACING_ENABLED", - "OPEN_TELEMETRY_TRACING_URL", - "OPEN_TELEMETRY_METRICS_HOST", - "OPEN_TELEMETRY_METRICS_PORT", - "OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY", - ]); - return { - metricsEnabled: Boolean(envs.OPEN_TELEMETRY_METRICS_ENABLED), - metricsHost: envs.OPEN_TELEMETRY_METRICS_HOST, - metricsPort: Number(envs.OPEN_TELEMETRY_METRICS_PORT), - metricsScrapingFrequency: Number( - envs.OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY - ), - tracingEnabled: Boolean(envs.OPEN_TELEMETRY_TRACING_ENABLED), - tracingUrl: envs.OPEN_TELEMETRY_TRACING_URL, - }; -} -export function parseSettlementEnv(envs: SettlementEnv): { - network: string; - graphql: string; - archive: string; - accountManager: string; - sequencerPrivateKey: string; - settlementContractPrivateKey: string; - dispatcherContractPrivateKey: string; - minaBridgeContractPrivateKey: string; -} { - ensureDefined(envs as Record, [ - "MINA_ACCOUNT_MANAGER_HOST", - "MINA_ACCOUNT_MANAGER_PORT", - "MINA_ARCHIVE_GRAPHQL_HOST", - "MINA_ARCHIVE_GRAPHQL_PORT", - "MINA_NODE_GRAPHQL_HOST", - "MINA_NODE_GRAPHQL_PORT", - "MINA_NETWORK", - "PROTOKIT_SEQUENCER_PRIVATE_KEY", - "PROTOKIT_SETTLEMENT_CONTRACT_PRIVATE_KEY", - "PROTOKIT_DISPATCHER_CONTRACT_PRIVATE_KEY", - "PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY", - ]); - - return { - network: envs.MINA_NETWORK!, - graphql: `${envs.MINA_NODE_GRAPHQL_HOST}:${envs.MINA_NODE_GRAPHQL_PORT}/graphql`, - archive: `${envs.MINA_ARCHIVE_GRAPHQL_HOST}:${envs.MINA_ARCHIVE_GRAPHQL_PORT}`, - accountManager: `${envs.MINA_ACCOUNT_MANAGER_HOST}:${envs.MINA_ACCOUNT_MANAGER_PORT}`, - sequencerPrivateKey: envs.PROTOKIT_SEQUENCER_PRIVATE_KEY!, - settlementContractPrivateKey: - envs.PROTOKIT_SETTLEMENT_CONTRACT_PRIVATE_KEY!, - dispatcherContractPrivateKey: - envs.PROTOKIT_DISPATCHER_CONTRACT_PRIVATE_KEY!, - minaBridgeContractPrivateKey: - envs.PROTOKIT_MINA_BRIDGE_CONTRACT_PRIVATE_KEY!, - }; -} -export function parseIndexerEnv(envs: IndexerEnv): { - redisHost?: string; - redisPort?: number; - redisPassword?: string; - indexerDatabaseUrl?: string; - graphqlPort?: number; - graphqlHost?: string; - graphiqlEnabled?: boolean; -} { - ensureDefined(envs as Record, [ - "REDIS_HOST", - "REDIS_PORT", - "REDIS_PASSWORD", - "INDEXER_DATABASE_URL", - "PROTOKIT_INDEXER_GRAPHQL_PORT", - "PROTOKIT_INDEXER_GRAPHQL_HOST", - "PROTOKIT_INDEXER_GRAPHIQL_ENABLED", - ]); - return { - redisHost: envs.REDIS_HOST, - redisPort: envs.REDIS_PORT ? Number(envs.REDIS_PORT) : undefined, - redisPassword: envs.REDIS_PASSWORD, - indexerDatabaseUrl: envs.INDEXER_DATABASE_URL, - graphqlPort: envs.PROTOKIT_INDEXER_GRAPHQL_PORT - ? Number(envs.PROTOKIT_INDEXER_GRAPHQL_PORT) - : undefined, - graphqlHost: envs.PROTOKIT_INDEXER_GRAPHQL_HOST, - graphiqlEnabled: envs.PROTOKIT_INDEXER_GRAPHIQL_ENABLED - ? Boolean(envs.PROTOKIT_INDEXER_GRAPHIQL_ENABLED) - : undefined, - }; -} -export function parseProcessorEnv(envs: ProcessorEnv): { - processorIndexerGraphqlHost?: string; - indexerGraphqlPort?: number; - blockInterval?: number; - processorGraphqlHost?: string; - processorGraphqlPort?: number; - processorGraphiqlEnabled?: boolean; -} { - ensureDefined(envs as Record, [ - "PROTOKIT_PROCESSOR_INDEXER_GRAPHQL_HOST", - "PROTOKIT_INDEXER_GRAPHQL_PORT", - "PROTOKIT_BLOCK_INTERVAL", - "PROTOKIT_PROCESSOR_GRAPHQL_HOST", - "PROTOKIT_PROCESSOR_GRAPHQL_PORT", - "PROTOKIT_PROCESSOR_GRAPHIQL_ENABLED", - ]); - return { - processorIndexerGraphqlHost: envs.PROTOKIT_PROCESSOR_INDEXER_GRAPHQL_HOST, - indexerGraphqlPort: envs.PROTOKIT_INDEXER_GRAPHQL_PORT - ? Number(envs.PROTOKIT_INDEXER_GRAPHQL_PORT) - : undefined, - blockInterval: envs.PROTOKIT_BLOCK_INTERVAL - ? Number(envs.PROTOKIT_BLOCK_INTERVAL) - : undefined, - processorGraphqlHost: envs.PROTOKIT_PROCESSOR_GRAPHQL_HOST, - processorGraphqlPort: envs.PROTOKIT_PROCESSOR_GRAPHQL_PORT - ? Number(envs.PROTOKIT_PROCESSOR_GRAPHQL_PORT) - : undefined, - processorGraphiqlEnabled: envs.PROTOKIT_PROCESSOR_GRAPHIQL_ENABLED - ? Boolean(envs.PROTOKIT_PROCESSOR_GRAPHIQL_ENABLED) - : undefined, - }; -} -export function parseDatabaseEnv(envs: DatabaseEnv): { - redisHost?: string; - redisPort?: number; - redisPassword?: string; - databaseUrl?: string; -} { - return { - redisHost: envs.REDIS_HOST, - redisPort: envs.REDIS_PORT ? Number(envs.REDIS_PORT) : undefined, - redisPassword: envs.REDIS_PASSWORD, - databaseUrl: envs.DATABASE_URL, - }; -} -export function parseTaskQueueEnv(envs: TaskQueueEnv): { - redisHost?: string; - redisPort?: number; - redisPassword?: string; -} { - return { - redisHost: envs.REDIS_HOST, - redisPort: envs.REDIS_PORT ? Number(envs.REDIS_PORT) : undefined, - redisPassword: envs.REDIS_PASSWORD, - }; -} -export function parseDatabasePruneEnv(envs: DatabasePruneEnv): { - pruneOnStartup: boolean; -} { - return { - pruneOnStartup: - envs.PRUNE_ON_STARTUP === "true" || envs.PRUNE_ON_STARTUP === true, - }; -} -export function parseGraphqlServerEnv( - envs: GraphqlServerEnv, - type: "protokit" | "indexer" | "processor" = "protokit" -): { - graphqlPort?: number; - graphqlHost?: string; - graphiqlEnabled?: boolean; -} { - const prefix = - type === "indexer" - ? "PROTOKIT_INDEXER" - : type === "processor" - ? "PROTOKIT_PROCESSOR" - : "PROTOKIT"; - return { - graphqlPort: envs[`${prefix}_GRAPHQL_PORT`] - ? Number(envs[`${prefix}_GRAPHQL_PORT`]) - : undefined, - graphqlHost: envs[`${prefix}_GRAPHQL_HOST`], - graphiqlEnabled: envs[`${prefix}_GRAPHIQL_ENABLED`] - ? Boolean(envs[`${prefix}_GRAPHIQL_ENABLED`]) - : undefined, - }; -} -export function parseRedisEnv(envs: RedisEnv): { - redisHost?: string; - redisPort?: number; - redisPassword?: string; -} { - return { - redisHost: envs.REDIS_HOST, - redisPort: envs.REDIS_PORT ? Number(envs.REDIS_PORT) : undefined, - redisPassword: envs.REDIS_PASSWORD, - }; -} diff --git a/packages/stack/src/presets/sequencer/index.ts b/packages/stack/src/presets/sequencer/index.ts deleted file mode 100644 index 1fd6919fb..000000000 --- a/packages/stack/src/presets/sequencer/index.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { SequencerModulesRecord, Sequencer } from "@proto-kit/sequencer"; -import { ModulesConfig, RecursivePartial } from "@proto-kit/common"; -import { DefaultConfigs, DefaultModules } from "../modules"; -import { definePreset } from "../modules/utils"; - -export class DefaultSequencer { - static inmemory(options?: { - overrideModules?: Partial; - settlementEnabled?: boolean; - }) { - const modules = DefaultModules.ordered( - definePreset( - { - ...DefaultModules.database(), - ...DefaultModules.core({ - settlementEnabled: options?.settlementEnabled, - }), - ...DefaultModules.taskQueue(), - ...(options?.settlementEnabled ? DefaultModules.settlement() : {}), - }, - options?.overrideModules - ) - ); - - return Sequencer.from(modules); - } - static development(options?: { - overrideModules?: Partial; - settlementEnabled?: boolean; - }) { - const modules = DefaultModules.ordered( - definePreset( - { - // ordering of the modules matters due to dependency resolution - ...DefaultModules.database({ preset: "development" }), - ...DefaultModules.databasePrune(), - ...DefaultModules.metrics(), - ...DefaultModules.taskQueue({ preset: "development" }), - ...DefaultModules.core({ - settlementEnabled: options?.settlementEnabled, - }), - ...DefaultModules.sequencerIndexer(), - }, - options?.overrideModules - ) - ); - - return Sequencer.from(modules); - } - static sovereign(options?: { - overrideModules?: Partial; - settlementEnabled?: boolean; - }) { - const modules = DefaultModules.ordered( - definePreset( - { - // ordering of the modules matters due to dependency resolution - ...DefaultModules.database(), - ...DefaultModules.taskQueue(), - ...DefaultModules.core({ - settlementEnabled: options?.settlementEnabled, - }), - ...DefaultModules.sequencerIndexer(), - ...DefaultModules.metrics(), - ...DefaultModules.databasePrune(), - }, - options?.overrideModules - ) - ); - - return Sequencer.from(modules); - } -} -export class DefaultSequencerConfig { - static inmemory(options?: { - overrideConfig?: RecursivePartial>; - settlementEnabled?: boolean; - }) { - return { - ...DefaultConfigs.core({ settlementEnabled: options?.settlementEnabled }), - ...DefaultConfigs.database({ preset: "inmemory" }), - ...DefaultConfigs.taskQueue({ preset: "inmemory" }), - ...options?.overrideConfig, - }; - } - static development(options?: { - overrideConfig?: RecursivePartial>; - settlementEnabled?: boolean; - }) { - return { - ...DefaultConfigs.core({ - settlementEnabled: options?.settlementEnabled, - preset: "development", - }), - ...DefaultConfigs.sequencerIndexer(), - ...DefaultConfigs.metrics({ preset: "development" }), - ...DefaultConfigs.databasePrune({ preset: "development" }), - ...DefaultConfigs.taskQueue({ - preset: "development", - overrides: { - ...DefaultConfigs.redis({ - preset: "development", - overrides: { db: 1 }, - }), - }, - }), - ...DefaultConfigs.database({ preset: "development" }), - ...options?.overrideConfig, - }; - } - static sovereign(options?: { - overrideConfig?: RecursivePartial>; - settlementEnabled?: boolean; - }) { - return { - ...DefaultConfigs.core({ - settlementEnabled: options?.settlementEnabled, - preset: "sovereign", - }), - ...DefaultConfigs.sequencerIndexer(), - ...DefaultConfigs.metrics({ preset: "sovereign" }), - ...DefaultConfigs.databasePrune({ preset: "sovereign" }), - ...DefaultConfigs.taskQueue({ - preset: "sovereign", - overrides: { - ...DefaultConfigs.redis({ - preset: "sovereign", - overrides: { db: 1 }, - }), - }, - }), - ...DefaultConfigs.database({ preset: "sovereign" }), - ...options?.overrideConfig, - }; - } -} From 3a05782bc6fc4b16160d48e9f567305ce16ae385 Mon Sep 17 00:00:00 2001 From: stanlou Date: Sat, 24 Jan 2026 11:25:45 +0100 Subject: [PATCH 3/4] fix code format --- packages/stack/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/stack/package.json b/packages/stack/package.json index dc3c50ad3..9258a54cc 100644 --- a/packages/stack/package.json +++ b/packages/stack/package.json @@ -41,7 +41,6 @@ "@prisma/client": "^5.19.1", "mina-fungible-token": "^1.1.0", "type-graphql": "2.0.0-rc.2" - }, "gitHead": "397881ed5d8f98f5005bcd7be7f5a12b3bc6f956" } From ea5e64a1db874da16685645c86ca79746266e93e Mon Sep 17 00:00:00 2001 From: stanlou Date: Sat, 24 Jan 2026 12:49:56 +0100 Subject: [PATCH 4/4] fix graphql server config --- packages/stack/src/presets/modules/index.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/stack/src/presets/modules/index.ts b/packages/stack/src/presets/modules/index.ts index d1067aadd..9c61fbdaf 100644 --- a/packages/stack/src/presets/modules/index.ts +++ b/packages/stack/src/presets/modules/index.ts @@ -196,7 +196,7 @@ export class DefaultConfigs { }) { return { Graphql: VanillaGraphqlModules.defaultConfig(), - GraphqlServer: DefaultConfigs.graphqlServer({ + ...DefaultConfigs.graphqlServer({ preset: options?.preset, overrides: options?.overrides, }), @@ -452,9 +452,11 @@ export class DefaultConfigs { ); return { - port: config.graphqlPort, - host: config.graphqlHost, - graphiql: config.graphiqlEnabled, + GraphqlServer: { + port: config.graphqlPort, + host: config.graphqlHost, + graphiql: config.graphiqlEnabled, + }, }; }