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/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 2851234e1..9258a54cc 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,10 @@ "@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", + "type-graphql": "2.0.0-rc.2" }, "gitHead": "397881ed5d8f98f5005bcd7be7f5a12b3bc6f956" } diff --git a/packages/stack/src/index.ts b/packages/stack/src/index.ts index 35d49ee83..fb31453cc 100644 --- a/packages/stack/src/index.ts +++ b/packages/stack/src/index.ts @@ -1 +1,5 @@ export * from "./scripts/graphql/server"; +export * from "./presets/config"; +export * from "./presets/modules/types"; +export * from "./presets/modules/utils"; +export * from "./presets/modules"; diff --git a/packages/stack/src/presets/config.ts b/packages/stack/src/presets/config.ts new file mode 100644 index 000000000..040b14f42 --- /dev/null +++ b/packages/stack/src/presets/config.ts @@ -0,0 +1,184 @@ +export const inmemoryConfig = { + blockInterval: 5000, + graphqlHost: "localhost", + graphqlPort: 8080, + graphiqlEnabled: true, +}; +export const developmentConfig = { + 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", + + indexerDatabaseUrl: + "postgresql://admin:password@localhost:5433/protokit-indexer?schema=public", + + processorDatabaseUrl: + "postgresql://admin:password@localhost:5434/protokit-processor?schema=public", + + graphqlHost: "0.0.0.0", + graphqlPort: 8080, + graphiqlEnabled: true, + + indexerGraphqlHost: "0.0.0.0", + indexerGraphqlPort: 8081, + indexerGraphqlEnabled: true, + + processorGraphqlHost: "0.0.0.0", + processorGraphqlPort: 8082, + processorGraphqlEnabled: true, + + processorIndexerGraphqlHost: "0.0.0.0", + + minaNetwork: "lightnet", + minaNodeGraphqlHost: "http://localhost", + minaNodeGraphqlPort: 8083, + + minaArchiveGraphqlHost: "http://localhost", + minaArchiveGraphqlPort: 8085, + + minaAccountManagerHost: "http://localhost", + minaAccountManagerPort: 8084, + minaExplorerPort: 3001, + + transactionFeeRecipientPrivateKey: + "EKEssvj33MMBCg2tcybTzL32nTKbbwFHm6yUxd3JassdhL3J5aT8", + transactionFeeRecipientPublicKey: + "B62qk4sNnzZqqjHp8YQXZUV3dBpnjiNieJVnsuh7mD2bMJ9PdbskH5H", + + sequencerPrivateKey: "EKEdKhgUHMuDvwWJEg2TdCMCeiTSd9hh2HrEr6uYJfPVuwur1s43", + sequencerPublicKey: "B62qizW6aroTxQorJz4ywVNZom4jA6W4QPPCK3wLeyhnJHtVStUNniL", + + settlementContractPrivateKey: + "EKErS9gYHZNawqKuwfMiwYYJtNptCrvca491QEvB3tz8sFsS5w66", + settlementContractPublicKey: + "B62qjKhzrvDgTPXCp34ozmpFSx4sC9owZe6eDzhdGPdoiUbGPmBkHTt", + + dispatcherContractPrivateKey: + "EKF9Ei5G9PeB5ULMh9R6P5LfWX2gs15XxPNsect1pbcbMY9vs6v7", + dispatcherContractPublicKey: + "B62qmAzUJ1jqcsEf2V3K1k2Ec4MLsEKnodEvvJ5uweTFSLYEUALe1zs", + + minaBridgeContractPrivateKey: + "EKFKTGqWU2egLKhMgoxX8mQ21zXSE1RZYkY82mmK9F3BxdSA7E5M", + minaBridgeContractPublicKey: + "B62qn8XRkWcaBvv6F7kvarKs4cViaKRMbTUHT8FrDXLnvxuV6n7CHsN", + + customTokenPrivateKey: "EKFZHQSo5YdrcU7neDaNZruYHvCiNncvdZyKXuS6MDCW1fyCFKDP", + + customTokenAdminPrivateKey: + "EKENQ2QRc4gAJkZjQXU86ZS9MDm1e7HFiNN6LgRJnniHJt1WXDn1", + + customTokenBridgePrivateKey: + "EKENQ2QRc4gAJkZjQXU86ZS9MDm1e7HFiNN6LgRJnniHJt1WXDn1", + + testAccount1PrivateKey: + "EKF5p3wQTFd4tRBiGicRf93yXK82bcRryokC1qoazRM6wq6gMzWJ", + testAccount1PublicKey: + "B62qkVfEwyfkm5yucHEqrRjxbyx98pgdWz82pHv7LYq9Qigs812iWZ8", + + openTelemetryTracingEnabled: true, + openTelemetryTracingUrl: "http://localhost:4318", + + openTelemetryMetricsEnabled: true, + openTelemetryMetricsHost: "0.0.0.0", + openTelemetryMetricsPort: 4320, + openTelemetryMetricsScrapingFrequency: 10, +}; +export const sovereignConfig = { + blockInterval: 10000, + settlementInterval: 30000, + settlementEnabled: true, + + shouldAttemptDbMigration: true, + shouldAttemptIndexerDbMigration: true, + shouldAttemptProcessorDbMigration: true, + + pruneOnStartup: false, + + redisHost: "redis", + redisPort: 6379, + redisPassword: "password", + + databaseUrl: + "postgresql://admin:password@postgres:5432/protokit?schema=public", + + indexerDatabaseUrl: + "postgresql://admin:password@indexer-postgres:5432/protokit-indexer?schema=public", + + processorDatabaseUrl: + "postgresql://admin:password@processor-postgres:5432/protokit-processor?schema=public", + + graphqlHost: "0.0.0.0", + graphqlPort: 8080, + graphiqlEnabled: true, + + indexerGraphqlHost: "0.0.0.0", + indexerGraphqlPort: 8081, + indexerGraphqlEnabled: true, + + processorGraphqlHost: "0.0.0.0", + processorGraphqlPort: 8082, + processorGraphqlEnabled: true, + processorIndexerGraphqlHost: "indexer", + + minaNetwork: "lightnet", + minaNodeGraphqlHost: "http://lightnet", + minaNodeGraphqlPort: 8080, + + minaArchiveGraphqlHost: "http://lightnet", + minaArchiveGraphqlPort: 8282, + + minaAccountManagerHost: "http://lightnet", + minaAccountManagerPort: 8084, + minaExplorerPort: 3001, + transactionFeeRecipientPrivateKey: + "EKEssvj33MMBCg2tcybTzL32nTKbbwFHm6yUxd3JassdhL3J5aT8", + transactionFeeRecipientPublicKey: + "B62qk4sNnzZqqjHp8YQXZUV3dBpnjiNieJVnsuh7mD2bMJ9PdbskH5H", + + sequencerPrivateKey: "EKEdKhgUHMuDvwWJEg2TdCMCeiTSd9hh2HrEr6uYJfPVuwur1s43", + sequencerPublicKey: "B62qizW6aroTxQorJz4ywVNZom4jA6W4QPPCK3wLeyhnJHtVStUNniL", + + settlementContractPrivateKey: + "EKErS9gYHZNawqKuwfMiwYYJtNptCrvca491QEvB3tz8sFsS5w66", + settlementContractPublicKey: + "B62qjKhzrvDgTPXCp34ozmpFSx4sC9owZe6eDzhdGPdoiUbGPmBkHTt", + + dispatcherContractPrivateKey: + "EKF9Ei5G9PeB5ULMh9R6P5LfWX2gs15XxPNsect1pbcbMY9vs6v7", + dispatcherContractPublicKey: + "B62qmAzUJ1jqcsEf2V3K1k2Ec4MLsEKnodEvvJ5uweTFSLYEUALe1zs", + + minaBridgeContractPrivateKey: + "EKFKTGqWU2egLKhMgoxX8mQ21zXSE1RZYkY82mmK9F3BxdSA7E5M", + minaBridgeContractPublicKey: + "B62qn8XRkWcaBvv6F7kvarKs4cViaKRMbTUHT8FrDXLnvxuV6n7CHsN", + + testAccount1PrivateKey: + "EKF5p3wQTFd4tRBiGicRf93yXK82bcRryokC1qoazRM6wq6gMzWJ", + testAccount1PublicKey: + "B62qkVfEwyfkm5yucHEqrRjxbyx98pgdWz82pHv7LYq9Qigs812iWZ8", + + openTelemetryTracingEnabled: true, + openTelemetryTracingUrl: "http://otel-collector:4317", + + 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 new file mode 100644 index 000000000..9c61fbdaf --- /dev/null +++ b/packages/stack/src/presets/modules/index.ts @@ -0,0 +1,518 @@ +import { + VanillaGraphqlModules, + GraphqlSequencerModule, + GraphqlServer, + OpenTelemetryServer, +} from "@proto-kit/api"; +import { + PrivateMempool, + SequencerModulesRecord, + TimedBlockTrigger, + BlockProducerModule, + SequencerStartupModule, + LocalTaskWorkerModule, + VanillaTaskWorkerModules, + MinaBaseLayer, + ConstantFeeStrategy, + BatchProducerModule, + SettlementModule, + DatabasePruneModule, + InMemoryDatabase, + LocalTaskQueue, + AppChainModulesRecord, +} from "@proto-kit/sequencer"; +import { + IndexerNotifier, + GeneratedResolverFactoryGraphqlModule, + IndexBlockTask, +} from "@proto-kit/indexer"; +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 { PrivateKey } from "o1js"; +import { NonEmptyArray } from "type-graphql"; + +import { + buildCustomTokenConfig, + buildSettlementTokenConfig, + resolveEnv, +} from "./utils"; +import { + Environment, + CoreEnv, + MetricsEnv, + IndexerEnv, + ProcessorEnv, + SettlementEnv, + RedisEnv, + DatabaseEnv, + RedisTaskQueueEnv, + GraphqlServerEnv, +} from "./types"; + +export class DefaultModules { + static api() { + return { + GraphqlServer, + Graphql: GraphqlSequencerModule.from(VanillaGraphqlModules.with({})), + } satisfies SequencerModulesRecord; + } + + 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() { + return { + OpenTelemetryServer, + } satisfies SequencerModulesRecord; + } + + static settlement() { + return { + BaseLayer: MinaBaseLayer, + FeeStrategy: ConstantFeeStrategy, + BatchProducerModule, + SettlementModule, + LocalTaskWorkerModule: LocalTaskWorkerModule.from( + VanillaTaskWorkerModules.allTasks() + ), + } satisfies SequencerModulesRecord; + } + + static sequencerIndexer() { + return { + IndexerNotifier, + } satisfies SequencerModulesRecord; + } + + 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 + ) { + return { + GraphqlServer, + GraphqlSequencerModule: GraphqlSequencerModule.from({ + ResolverFactory: ResolverFactoryGraphqlModule.from(resolvers), + }), + HandlersExecutor: HandlersExecutor.from(handlers), + BlockFetching, + Trigger: TimedProcessorTrigger, + } satisfies SequencerModulesRecord; + } + + static inMemoryDatabase() { + return { + Database: InMemoryDatabase, + } satisfies SequencerModulesRecord; + } + + static PrismaRedisDatabase() { + return { + Database: PrismaRedisDatabase, + DatabasePruneModule, + } satisfies SequencerModulesRecord; + } + + static localTaskQueue() { + return { + TaskQueue: LocalTaskQueue, + } satisfies SequencerModulesRecord; + } + + static RedisTaskQueue() { + return { + TaskQueue: BullQueue, + } satisfies SequencerModulesRecord; + } + + static worker() { + return { + TaskQueue: BullQueue, + LocalTaskWorkerModule: LocalTaskWorkerModule.from( + VanillaTaskWorkerModules.allTasks() + ), + } satisfies SequencerModulesRecord; + } + + static appChainBase() { + return { + TransactionSender: InMemoryTransactionSender, + QueryTransportModule: StateServiceQueryModule, + NetworkStateTransportModule: BlockStorageNetworkStateModule, + } satisfies AppChainModulesRecord; + } + + static settlementScript() { + return { + ...DefaultModules.settlement(), + Mempool: PrivateMempool, + TaskQueue: LocalTaskQueue, + SequencerStartupModule, + } satisfies SequencerModulesRecord; + } +} +export class DefaultConfigs { + static api(options?: { + preset?: Environment; + overrides?: Partial; + }) { + return { + Graphql: VanillaGraphqlModules.defaultConfig(), + ...DefaultConfigs.graphqlServer({ + preset: options?.preset, + overrides: options?.overrides, + }), + }; + } + + static core(options?: { + preset?: Environment; + overrides?: Partial & + Partial & + Partial; + settlementEnabled?: boolean; + }) { + const settlementEnabled = options?.settlementEnabled ?? false; + const config = resolveEnv(options?.preset, options?.overrides); + const apiConfig = DefaultConfigs.api({ + preset: options?.preset, + overrides: options?.overrides, + }); + const settlementConfig = settlementEnabled + ? DefaultConfigs.settlement({ + preset: options?.preset, + overrides: options?.overrides, + }) + : {}; + const blockTriggerConfig = { + blockInterval: config.blockInterval, + produceEmptyBlocks: true, + ...(settlementEnabled + ? { + settlementInterval: config.settlementInterval, + settlementTokenConfig: buildSettlementTokenConfig( + config.minaBridgeContractPrivateKey!, + buildCustomTokenConfig( + config.customTokenPrivateKey, + config.customTokenBridgePrivateKey + ) + ), + } + : { settlementTokenConfig: {} }), + }; + + return { + ...apiConfig, + Mempool: {}, + BlockProducerModule: {}, + BlockTrigger: blockTriggerConfig, + SequencerStartupModule: {}, + LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + ...settlementConfig, + }; + } + + static metrics(options?: { + preset?: Environment; + overrides?: Partial; + }) { + const config = resolveEnv(options?.preset, options?.overrides); + return { + OpenTelemetryServer: { + metrics: { + enabled: config.metricsEnabled, + prometheus: { + host: config.metricsHost, + port: config.metricsPort, + appendTimestamp: true, + }, + nodeScrapeInterval: config.metricsScrapingFrequency, + }, + tracing: { + enabled: config.tracingEnabled, + otlp: { + url: config.tracingUrl, + }, + }, + }, + }; + } + + static sequencerIndexer() { + return { IndexerNotifier: {} }; + } + + static indexer(options?: { + preset?: Environment; + overrides?: Partial; + }) { + const config = resolveEnv(options?.preset, options?.overrides); + const taskQueueConfig = DefaultConfigs.redisTaskQueue({ + preset: options?.preset, + overrides: options?.overrides, + }); + const databaseConfig = DefaultConfigs.prismaRedisDatabase({ + preset: options?.preset, + overrides: { + databaseUrl: config.indexerDatabaseUrl, + ...options?.overrides, + }, + }); + const graphqlServerConfig = DefaultConfigs.graphqlServer({ + preset: options?.preset, + overrides: { + graphqlHost: config.indexerGraphqlHost, + graphqlPort: config.indexerGraphqlPort, + graphiqlEnabled: config.indexerGraphqlEnabled, + ...options?.overrides, + }, + }); + + return { + ...databaseConfig, + ...taskQueueConfig, + TaskWorker: { + IndexBlockTask: {}, + }, + ...graphqlServerConfig, + Graphql: { + GeneratedResolverFactory: {}, + }, + }; + } + + static processor(options?: { + preset?: Environment; + overrides?: Partial; + }) { + const config = resolveEnv( + options?.preset, + options?.overrides + ); + const graphqlServerConfig = DefaultConfigs.graphqlServer({ + preset: options?.preset, + overrides: { + graphqlHost: config.processorGraphqlHost, + graphqlPort: config.processorGraphqlPort, + graphiqlEnabled: config.processorGraphqlEnabled, + ...options?.overrides, + }, + }); + return { + HandlersExecutor: {}, + BlockFetching: { + url: `http://${config.processorIndexerGraphqlHost}:${config.indexerGraphqlPort}`, + }, + Trigger: { + interval: Number(config.blockInterval) / 5, + }, + ...graphqlServerConfig, + GraphqlSequencerModule: { + ResolverFactory: {}, + }, + }; + } + + static settlement(options?: { + preset?: Environment; + 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(config.sequencerPrivateKey), + keys: { + settlement: PrivateKey.fromBase58( + config.settlementContractPrivateKey + ), + dispatch: PrivateKey.fromBase58(config.dispatcherContractPrivateKey), + minaBridge: PrivateKey.fromBase58( + config.minaBridgeContractPrivateKey + ), + }, + }, + FeeStrategy: {}, + BatchProducerModule: {}, + LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + }; + } + + static inMemoryDatabase() { + return { Database: {} }; + } + + static prismaRedisDatabase(options?: { + preset?: Environment; + overrides?: Partial; + }) { + const preset = options?.preset ?? "development"; + const config = resolveEnv(preset, options?.overrides); + const redisConfig = DefaultConfigs.redis({ + preset, + overrides: options?.overrides, + }); + return { + Database: { + ...redisConfig, + prisma: { + connection: config.databaseUrl, + }, + }, + DatabasePruneModule: { + pruneOnStartup: config.pruneOnStartup, + }, + }; + } + + static localTaskQueue() { + return { + TaskQueue: {}, + }; + } + + static redisTaskQueue(options?: { + preset?: Environment; + overrides?: Partial; + }) { + const config = resolveEnv( + options?.preset, + options?.overrides + ); + + return { + TaskQueue: { + redis: { + host: config.redisHost, + port: config.redisPort, + password: config.redisPassword, + db: config.redisDb, + }, + retryAttempts: config.retryAttempts, + }, + }; + } + + static graphqlServer(options?: { + preset?: Environment; + overrides?: Partial; + }) { + const config = resolveEnv( + options?.preset, + options?.overrides + ); + + return { + GraphqlServer: { + port: config.graphqlPort, + host: config.graphqlHost, + graphiql: config.graphiqlEnabled, + }, + }; + } + + static redis(options?: { + preset?: Environment; + overrides?: Partial; + }) { + const config = resolveEnv(options?.preset, options?.overrides); + + return { + redis: { + host: config.redisHost, + port: config.redisPort, + password: config.redisPassword, + }, + }; + } + + static appChainBase() { + return { + QueryTransportModule: {}, + NetworkStateTransportModule: {}, + TransactionSender: {}, + }; + } + + static worker(options?: { + preset?: Environment; + overrides?: Partial; + }) { + const taskQueueConfig = DefaultConfigs.redisTaskQueue({ + preset: options?.preset, + overrides: options?.overrides, + }); + + return { + ...taskQueueConfig, + LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + }; + } + + static settlementScript(options?: { + preset?: Environment; + overrides?: Partial; + }) { + const settlementConfig = DefaultConfigs.settlement({ + preset: options?.preset, + overrides: options?.overrides, + }); + return { + ...settlementConfig, + SequencerStartupModule: {}, + TaskQueue: { + simulatedDuration: 0, + }, + Mempool: {}, + }; + } +} diff --git a/packages/stack/src/presets/modules/types.ts b/packages/stack/src/presets/modules/types.ts new file mode 100644 index 000000000..65efe1603 --- /dev/null +++ b/packages/stack/src/presets/modules/types.ts @@ -0,0 +1,63 @@ +export type Environment = "inmemory" | "development" | "sovereign"; + +export type GraphqlServerEnv = { + graphqlPort: number; + graphqlHost: string; + graphiqlEnabled: boolean; +}; +export type CoreEnv = { + blockInterval: number; + settlementInterval?: number; + minaBridgeContractPrivateKey?: string; + customTokenPrivateKey?: string; + customTokenBridgePrivateKey?: string; +}; +export type MetricsEnv = { + metricsEnabled: boolean; + metricsHost: string; + metricsPort: number; + metricsScrapingFrequency: number; + tracingEnabled: boolean; + tracingUrl: string; +}; +export type SettlementEnv = { + 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 = { + processorIndexerGraphqlHost: string; + indexerGraphqlPort: number; + blockInterval: number; + processorGraphqlHost: string; + processorGraphqlPort: number; + processorGraphqlEnabled: boolean; +}; +export type DatabaseEnv = RedisEnv & { + databaseUrl: string; + pruneOnStartup?: boolean; +}; +export type RedisEnv = { + 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 new file mode 100644 index 000000000..ebe16616f --- /dev/null +++ b/packages/stack/src/presets/modules/utils.ts @@ -0,0 +1,62 @@ +import { PrivateKey, TokenId } from "o1js"; +import { FungibleToken } from "mina-fungible-token"; + +import { developmentConfig, inmemoryConfig, sovereignConfig } from "../config"; + +import { Environment } from "./types"; + +export function getConfigs(preset: Environment) { + switch (preset) { + case "development": + return developmentConfig; + case "sovereign": + return sovereignConfig; + case "inmemory": + default: + return inmemoryConfig; + } +} +export function resolveEnv( + preset: Environment = "inmemory", + envs?: Partial | undefined +): 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 +) { + if ( + customTokenPrivateKey === undefined || + customTokenBridgePrivateKey === undefined + ) { + 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 = {} +) { + return { + "1": { + bridgingContractPrivateKey: PrivateKey.fromBase58(bridgePrivateKey), + }, + ...customTokens, + }; +}