Skip to content

Commit 7f743dd

Browse files
authored
Merge pull request #65 from proto-kit/feat/starter-kit-documunetation
Feat/starter kit documunetation
2 parents e366de7 + 52d7fec commit 7f743dd

9 files changed

Lines changed: 324 additions & 5 deletions

File tree

src/pages/docs/quickstart/_meta.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export default {
2+
"starter-kit": "Starter Kit",
23
"app-chain": "App-chain's runtime",
34
configuration: "Configuration",
45
"first-runtime-module": "Implementing runtime modules",
Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
import { Tabs } from "nextra/components";
2+
3+
# Starter Kit
4+
5+
The Protokit starter-kit is a monorepo that provides a complete foundation for building application chains using the Protokit framework. It demonstrates how to structure your app-chain, configure runtime modules, and deploy across different environments.
6+
7+
For installation and initial setup, see the [QuickStart guide](/docs/quickstart).
8+
9+
## Default Environments
10+
11+
The starter-kit comes with three default environments, each tailored for different stages of development and deployment. Choose the one that fits your current workflow:
12+
13+
<Tabs items={['inmemory', 'development', 'sovereign']}>
14+
<Tabs.Tab>
15+
#### Inmemory Environment
16+
17+
Perfect for rapid testing and experimentation, this environment keeps all state in memory without any persistence.
18+
Use it to quickly iterate on runtime logic and test new features before moving to persistent environments.
19+
20+
**Characteristics:**
21+
- All state stored in memory
22+
- No external services or databases
23+
- Blocks are produced but not persisted
24+
- Perfect for unit and integration testing
25+
26+
**Chain Configuration (`chain.config.ts`):**
27+
28+
```typescript showLineNumbers filename="chain.config.ts" file=<rootDir>/starter-kit-snippets/packages/chain/src/core/environments/inmemory/chain.config.ts inline
29+
// group appchain-def
30+
```
31+
32+
- **`WorkerModule.withoutSettlement()`** : Configures the worker without settlement capabilities so that your sequencer will focus purely on producing blocks without attempting to settle to L1.
33+
- **`LocalTaskQueue`** : Handles tasks locally without external queue infrastructure.
34+
- **`LocalSequencerCoreModule`** : Allows registration of `BlockProducerModule` and `SequencerStartupModule` for local block production and initialization.
35+
- **`InMemoryDatabase`** : All state is stored in memory, no persistence across restarts.
36+
37+
**How to Run:**
38+
39+
Start the inmemory environment with both the UI and sequencer running with live reload:
40+
41+
```bash
42+
pnpm env:inmemory dev
43+
```
44+
45+
Then visit:
46+
- **UI:** http://localhost:3000
47+
- **Sequencer GraphQL:** http://localhost:8080/graphql
48+
49+
For running tests:
50+
```bash
51+
pnpm env:inmemory run test --filter=chain -- --watchAll
52+
```
53+
54+
</Tabs.Tab>
55+
56+
<Tabs.Tab>
57+
#### Development Environment
58+
59+
A complete development environment, where you can run sequencer, worker, indexer, and processor locally.
60+
Enables testing settlement logic and historical data indexing with all components running in separate processes.
61+
62+
**Characteristics:**
63+
- PostgreSQL databases for persistent state
64+
- Redis for caching and task queuing
65+
- Settlement and bridging to L1 enabled
66+
- Indexer for historical data
67+
- Processor for custom business logic
68+
- All components run in separate processes
69+
70+
**Chain Configuration (`chain.config.ts`):**
71+
72+
```typescript showLineNumbers filename="chain.config.ts" file=<rootDir>/starter-kit-snippets/packages/chain/src/core/environments/development/chain.config.ts inline
73+
// group sequencer-def
74+
```
75+
76+
77+
**Persistence & Settlement:**
78+
- **`Database: PrismaRedisDatabase`** : Uses Redis and PostgreSQL database to persists the sequencer states.
79+
- **`...protocol.settlementModules`** & **`...baseSettlementSequencerModules`** : Enables settlement and bridging to L1 (Mina). Your sequencer can now bridge tokens and settle state to the L1.
80+
81+
**Task Processing:**
82+
- **`TaskQueue: BullQueue`** : Uses BullMQ (backed by Redis) to handle asynchronous tasks. Tasks are processed in a separate worker processes.
83+
- **`SequencerCoreModule`** : In addition to `BlockProducerModule` and `SequencerStartupModule`, also registers `BatchProducerModule` for batch processing of blocks.
84+
85+
**Indexing:**
86+
- **`IndexerNotifier`** : Notifies the indexer about produced blocks, transactions, batches, and settlements, enabling historical data synchronization.
87+
88+
**Indexer Configuration (`indexer.config.ts`):**
89+
90+
```typescript showLineNumbers filename="indexer.config.ts" file=<rootDir>/starter-kit-snippets/packages/chain/src/core/environments/development/indexer.config.ts inline
91+
// group indexer-def
92+
```
93+
94+
**Indexer Details:**
95+
- **Separate Database** : Uses its own PostgreSQL database (configured via `PrismaRedisDatabase`) to store indexed data independently from the sequencer
96+
- **BullQueue Subscription** : Listens to the Redis-backed task queue for events emitted by the sequencer
97+
- **Task Processing** : Handles indexing of blocks, transactions, batches, and settlements
98+
- **GraphQL Endpoint** : Serves a separate GraphQL API for querying historical data
99+
100+
**Worker Configuration (`worker.config.ts`):**
101+
102+
```typescript showLineNumbers filename="worker.config.ts" file=<rootDir>/starter-kit-snippets/packages/chain/src/core/environments/development/worker.config.ts inline
103+
// group worker-def
104+
```
105+
106+
**Worker Details:**
107+
- **Separate Process** : Unlike inmemory environment, the worker runs in a different process and connects via BullQueue
108+
- **`VanillaTaskWorkerModules.allTasks()`** : Handles all tasks emitted by the sequencer
109+
110+
**Processor Configuration (`processor.config.ts`):**
111+
112+
```typescript
113+
const processor = Processor.from({
114+
Database: databaseModule,
115+
DatabasePruneModule: DatabasePruneModule,
116+
GraphqlSequencerModule: GraphqlSequencerModule.from({
117+
ResolverFactory: ResolverFactoryGraphqlModule.from(resolvers),
118+
}),
119+
HandlersExecutor: HandlersExecutor.from(handlers),
120+
BlockFetching,
121+
Trigger: TimedProcessorTrigger,
122+
});
123+
```
124+
**Processor Details:**
125+
- **Custom Database** : Uses a dedicated database to store processed data according to your schema
126+
- **Block Processing** : Fetches blocks from the indexer and processes them through your custom handlers
127+
- **Handler Execution** : Runs your defined business logic handlers
128+
- **GraphQL API** : Exposes processed data via GraphQL resolvers
129+
- **Timed Trigger** : Periodically checks for new blocks to process
130+
131+
**Services:**
132+
- Sequencer (port 8080) - Main GraphQL API
133+
- Indexer (port 8081) - Historical data GraphQL API
134+
- Processor (port 8082) - Processed data GraphQL API
135+
- PostgreSQL (ports 5432, 5433, 5434) - Three databases
136+
- Redis (port 6379) - Task queue and caching
137+
- Lightnet (ports 8083, 8085) - Local Mina network for settlement
138+
139+
**How to Run:**
140+
141+
First, start the containerized dependencies and set up databases:
142+
143+
```bash
144+
# Start PostgreSQL and Redis containers
145+
pnpm env:development docker:up -d
146+
147+
# Generate Prisma clients
148+
pnpm env:development prisma:generate
149+
150+
# Run migrations
151+
pnpm env:development prisma:migrate
152+
```
153+
154+
Then run each component in separate terminals:
155+
156+
```bash
157+
pnpm env:development worker:dev
158+
159+
pnpm env:development indexer:dev
160+
161+
pnpm env:development processor:dev
162+
163+
pnpm env:development dev
164+
```
165+
166+
Access your app-chain:
167+
- **UI:** http://localhost:3000
168+
- **Sequencer GraphQL:** http://localhost:8080/graphql
169+
- **Indexer GraphQL:** http://localhost:8081/graphql
170+
- **Processor GraphQL:** http://localhost:8082/graphql
171+
172+
</Tabs.Tab>
173+
174+
<Tabs.Tab>
175+
#### Sovereign Environment
176+
177+
A production-ready deployment with all services containerized, monitoring stack included, and reverse proxy for routing.
178+
Designed for deployments with full settlement capabilities, bridging support, and observability through metrics and tracing.
179+
180+
**Characteristics:**
181+
- All services run in Docker containers
182+
- PostgreSQL databases for persistent state
183+
- Redis for task queuing
184+
- Full monitoring stack (Grafana, Prometheus, Loki)
185+
- Settlement and bridging to L1 enabled
186+
- Caddy reverse proxy
187+
188+
**Chain Configuration (`chain.config.ts`):**
189+
190+
```typescript showLineNumbers filename="chain.config.ts" file=<rootDir>/starter-kit-snippets/packages/chain/src/core/environments/sovereign/chain.config.ts inline
191+
// group sequencer-def
192+
```
193+
194+
195+
**Observability & Monitoring:**
196+
- **`...metricsSequencerModules`** : Enables comprehensive observability with OpenTelemetry tracing and metrics collection for production monitoring
197+
198+
**Indexer Configuration (`indexer.config.ts`):**
199+
200+
```typescript showLineNumbers filename="indexer.config.ts" file=<rootDir>/starter-kit-snippets/packages/chain/src/core/environments/sovereign/indexer.config.ts inline
201+
// group indexer-def
202+
```
203+
204+
**Indexer Details:**
205+
- **Separate Container** : Runs in its own Docker container with dedicated PostgreSQL database
206+
- **OpenTelemetry Integration** : Built-in tracing and metrics for production monitoring
207+
- **Redis Task Queue** : Subscribes to BullQueue tasks
208+
- **GraphQL API** : Exposes on port 8081 through Caddy reverse proxy
209+
- **Prometheus Metrics** : Exports metrics for Grafana dashboards
210+
211+
**Worker Configuration (`worker.config.ts`):**
212+
213+
The sovereign environment supports **multiple worker variants** for specialized task processing:
214+
215+
```typescript showLineNumbers filename="worker.config.ts" file=<rootDir>/starter-kit-snippets/packages/chain/src/core/environments/sovereign/worker.config.ts inline
216+
// group worker-variants
217+
```
218+
219+
**Docker Services (`.env` COMPOSE_PROFILES):**
220+
221+
```bash
222+
COMPOSE_PROFILES=db,monolithic-sequencer,proxy,web,worker-monolithic,indexer,monitoring,explorer,lightnet
223+
```
224+
225+
**Services:**
226+
- **`db`** : PostgreSQL databases (sequencer, indexer, processor)
227+
- **`monolithic-sequencer`** : Sequencer container
228+
- **`proxy`** : Caddy reverse proxy for HTTPS and routing
229+
- **`web`** : Next.js UI container
230+
- **`worker-monolithic`** : Worker container
231+
- **`indexer`** : Indexer container
232+
- **`monitoring`** : Grafana, Prometheus, Loki stack
233+
- **`explorer`** : Protokit explorer UI
234+
- **`lightnet`** : Local Mina network for settlement
235+
236+
237+
238+
**Services Access (Behind Caddy Proxy):**
239+
- **UI:** `https://yourdomain.com`
240+
- **Sequencer GraphQL:** `https://yourdomain.com/graphql`
241+
- **Indexer GraphQL:** `https://yourdomain.com/indexer/graphql`
242+
- **Processor GraphQL:** `https://yourdomain.com/processor/graphql`
243+
- **Explorer:** `https://explorer.yourdomain.com`
244+
- **Grafana:** `https://grafana.yourdomain.com`
245+
246+
**For Production Deployment:**
247+
248+
Replace the wildcard configuration with your actual domain:
249+
250+
```
251+
yourdomain.com {
252+
reverse_proxy /graphql sequencer:8080
253+
reverse_proxy /indexer/graphql indexer:8081
254+
reverse_proxy /processor/graphql processor:8082
255+
reverse_proxy web:3000
256+
encode gzip
257+
}
258+
259+
explorer.yourdomain.com {
260+
reverse_proxy explorer:3000
261+
}
262+
263+
grafana.yourdomain.com {
264+
reverse_proxy grafana:3000
265+
}
266+
```
267+
268+
**How to Run:**
269+
270+
First, build the Docker images:
271+
272+
```bash
273+
pnpm env:sovereign docker:build
274+
```
275+
276+
Then start all services:
277+
278+
```bash
279+
# Start all containerized services
280+
pnpm env:sovereign docker:up -d
281+
```
282+
283+
Access your app-chain:
284+
- **UI:** https://localhost
285+
- **Sequencer GraphQL:** https://localhost/graphql
286+
- **Indexer GraphQL:** https://localhost/indexer/graphql
287+
- **Processor GraphQL:** https://localhost/processor/graphql
288+
- **Grafana:** https://grafana.localhost
289+
- **Explorer:** https://explorer.localhost.com
290+
291+
</Tabs.Tab>
292+
</Tabs>
293+
294+
> You can create custom environments using the [`wizard`](/docs/running/cli#wizard) command from the CLI. This allows you to configure additional environment setups tailored to your specific needs.
295+
296+
## The Complete Picture
297+
298+
Here's the flow of data and configuration in the starter-kit:
299+
300+
1. **Runtime Modules** (`runtime/modules/`) define what your app-chain can do
301+
2. **Protocol** (`protocol/index.ts`) defines the rules governing your app-chain
302+
3. **Sequencer Config** (`core/environments/{env}/chain.config.ts`) assembles the sequencer from:
303+
- Your runtime modules
304+
- Protocol rules
305+
- Sequencer infrastructure (database, GraphQL, mempool)
306+
4. **Environment Config** (`core/environments/{env}/.env`) provides runtime parameters
307+
5. **Client Config** (`core/environments/client.config.ts`) configure the client appchain
308+
6. **Docker Services** (`docker/`) runs databases, indexer, processor, lightnet etc.
309+
7. **Frontend** (`apps/web/`) connects via the client config and communicates with the sequencer GraphQL API

starter-kit-snippets/packages/chain/src/core/environments/development/chain.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
} from "../../sequencer";
3232

3333
const appChain = AppChain.from({
34+
// group sequencer-def
3435
Runtime: Runtime.from(runtime.modules),
3536
Protocol: Protocol.from({
3637
...protocol.modules,
@@ -47,6 +48,7 @@ const appChain = AppChain.from({
4748
TaskQueue: BullQueue,
4849
IndexerNotifier,
4950
}),
51+
// group sequencer-def
5052
TransactionSender: InMemoryTransactionSender,
5153
QueryTransportModule: StateServiceQueryModule,
5254
NetworkStateTransportModule: BlockStorageNetworkStateModule,

starter-kit-snippets/packages/chain/src/core/environments/development/indexer.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { BullQueue } from "@proto-kit/deployment";
1313
import { Arguments } from "../../../start";
1414
import { Startable } from "@proto-kit/common";
1515

16+
// group indexer-def
1617
const indexer = Indexer.from({
1718
Database: PrismaRedisDatabase,
1819
TaskQueue: BullQueue,
@@ -26,6 +27,7 @@ const indexer = Indexer.from({
2627
GeneratedResolverFactory: GeneratedResolverFactoryGraphqlModule,
2728
}),
2829
});
30+
// group indexer-def
2931

3032
export default async (args: Arguments): Promise<Startable> => {
3133
indexer.configurePartial({

starter-kit-snippets/packages/chain/src/core/environments/development/worker.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { Arguments } from "../../../start";
1313

1414
import { log, Startable } from "@proto-kit/common";
1515

16+
// group worker-def
1617
const appChain = AppChain.from({
1718
Runtime: Runtime.from(runtime.modules),
1819
Protocol: Protocol.from({
@@ -24,6 +25,7 @@ const appChain = AppChain.from({
2425
WorkerModule: WorkerModule.from(VanillaTaskWorkerModules.allTasks()),
2526
}),
2627
});
28+
// group worker-def
2729

2830
export default async (args: Arguments): Promise<Startable> => {
2931
appChain.configure({

starter-kit-snippets/packages/chain/src/core/environments/inmemory/chain.config.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,26 @@ import { Startable } from "@proto-kit/common";
2222
import protocol from "../../../protocol";
2323
import runtime from "../../../runtime";
2424

25-
//group appchain-def-1
25+
// group appchain-def
2626
const appChain = AppChain.from({
2727
Runtime: Runtime.from(runtime.modules),
2828
Protocol: Protocol.from(protocol.modules),
2929
Sequencer: Sequencer.from({
30-
//group appchain-def-1
3130
WorkerModule: WorkerModule.from(
3231
VanillaTaskWorkerModules.withoutSettlement()
3332
),
3433
TaskQueue: LocalTaskQueue,
3534
LocalSequencerCoreModule,
36-
//group appchain-def-2
3735
Database: InMemoryDatabase,
3836
Mempool: PrivateMempool,
39-
//group appchain-def-2
4037
Graphql: GraphqlSequencerModule.from(VanillaGraphqlModules.with({})),
4138
BlockTrigger: TimedBlockTrigger,
4239
}),
43-
// appchain modules
4440
TransactionSender: InMemoryTransactionSender,
4541
QueryTransportModule: StateServiceQueryModule,
4642
NetworkStateTransportModule: BlockStorageNetworkStateModule,
4743
});
44+
// group appchain-def
4845

4946
//group appchain-conf-1
5047
export default async (): Promise<Startable> => {

0 commit comments

Comments
 (0)