This repository is a monorepo aimed at kickstarting application chain development using the Protokit framework. You can learn more about the Protokit framework at the official documentation, or at the official Mina discord.
Prerequisites:
- Node.js
v18.18
(we recommend using NVM) - pnpm
v9.8.0
- nvm
- (optional) For running with persistance / deploying on a server
- docker
>= 24.0
- docker-compose
>= 2.22.0
- docker
Run the following commands to get started:
# clone the repository
git clone https://github.com/proto-kit/starter-kit my-chain
cd my-chain
# ensures you have the right node.js version
nvm use
# install dependencies
pnpm install
# starts both the UI and the sequencer (file watcher / live reload enabled)
pnpm env:inmemory dev
Visit http://localhost:3000 to view the example UI, or http://localhost:8080/graphql to explore the sequencer's GraphQL APIs.
The starter kit contains the following files and folders:
├── apps
│ └── web // example UI that connects to the app-chain's sequencer
│ ├── components // display components
│ ├── containers // smart components ("containers")
│ └── lib
│ └── stores // data stores for interacting with the app-chain's sequencer
│
├── docker
│ └── data // mounted as a volume for the docker containers
│
└── packages
└── chain
├── src // source files for various app-chain modules
│ ├── app-chain // app-chain modules (signers, queries, ...)
│ ├── environments // app-chain environments (inmemory, development, ...)
│ ├── indexer // indexer configuration (graphql server, storage services, ...)
├── processor // processor configuration (handlers, graphql resolvers, graphql server, ...)
│ ├── protocol // protocol modules (transaction fees, ...)
│ ├── runtime // runtime modules (your app-chain's business logic, such as balances)
│ │ └── modules
│ │ └── balances.ts // built-in example runtime module for Balances, with a faucet
│ ├── sequencer // sequencer modules (graphql server, mempool, block production, ...)
└── test // tests for various app-chain components
└── runtime
└── modules
└── balances.test.ts
The starter-kit offers different environments to run you appchain. You can use those environments to configure the mode of operation for your appchain depending on which stage of development you are in.
The starter kit comes with a set of pre-configured environments:
inmemory
: Runs everything in-memory without persisting the data. Useful for early stages of runtime development.development
: Runs the sequencer locally and persists all state in databases running in docker.sovereign
: Runs your appchain fully in docker (including the UI) for testnet deployments without settlement or bridging.
Every command you execute should follow this pattern:
pnpm env:<environment> <command>
This makes sure that everything is set correctly and our tooling knows which environment you want to use.
Each environment comes with a set of environment variables specified in .env
. This allows for configuration for the Protokit app-chain stack.
To learn more about what configuration options are available, check out any of the available env files at packages/chain/src/environments/<environment>/.env
# run and watch tests for the `chain` package
pnpm env:inmemory run test --filter=chain -- --watchAll
This step isn't required if you're using the
inmemory
environment.
# run dockerized dependencies in the background
pnpm env:development docker:up -d
# generate prisma clients
pnpm env:development prisma:generate
# migrate database schemas
pnpm env:development prisma:migrate
Persisted data is stored under docker/data
, you can delete this folder in case you're experiencing issues with persistence and need to reset your environment setup entirely.
However to prune data during development, you should use the --pruneOnStartup
CLI option documented here
Ensure you've successfully started the dockerized dependencies, generated and migrated all prisma schemas before running the sequencer (or indexer) in the development environment. In case of using the inmemory environment, you don't need to start the dockerized dependencies.
⚠️ Be aware, the dev command will automatically restart your application when your sources change. Please keep in mind that running the components below indev
mode (with live reload / watchersr) is advisable only when you're working on that specific component. In case you're experiencing issues with watches cross-triggering reload of different components, you can use thestart
command instead.
pnpm env:development sequencer:dev --filter=chain
pnpm env:development build --filter=chain
pnpm env:development sequencer:start --filter=chain
pnpm env:development dev --filter=web
You can also build/start the UI as well, instead of using
dev
command with live-reload.
inmemory
environment
pnpm env:development indexer:dev --filter=chain
Indexer's graphql is available at http://localhost:8081/graphql
, unless your environment configuraton specifies otherwise.
inmemory
environment
pnpm env:development processor:dev --filter=chain
Processor's graphql is available at http://localhost:8082/graphql
, unless your environment configuraton specifies otherwise.
logLevel
: Overrides the loglevel used. Also configurable via thePROTOKIT_LOG_LEVEL
environment variable.pruneOnStartup
: If set, prunes the database before startup, so that your chain is starting from a clean, genesis state. Alias for environment variablePROTOKIT_PRUNE_ON_STARTUP
In order to pass in those CLI option, add it at the end of your command like this
pnpm env:inmemory dev --filter chain -- --logLevel DEBUG --pruneOnStartup
Starter-kit ships with a preconfigured historical data processor using @proto-kit/processor
. Example block & transactions handlers are available in chain/src/processor/handlers/*
. Once the sequencer produces a block, it flows to the indexer for historical storage, and it's picked up by the processor via the indexer graphql API. The processor then runs the specified handlers in order to process the available block & transaction data into the user specified schema. Additionally the processor serves the processed data via a set of auto-generated graphql resolvers.
- Define your database schema at
chain/src/processor/prisma/schema.prisma
- Generate the prisma client using
pnpm env:<your_environment_name> run processor:prisma:generate
- Generate your database migrations using
pnpm env:<your_environment_name> run processor:prisma:migrate:dev
- Write your handlers as shows in
chain/src/processor/handlers/**
- Run the processor using
pnpm env:<your_environment_name> run processor:dev
(sequencer & indexer should be running beforehand)
Processor relies on the sequencer to produce blocks, and the indexer to access them
Once the processor starts, you can observe it query the indexer for blocks from the last processed block (starting at #0) and running the defined onBlock handler for each block.
Finally, you can query the processed data at the indexer's graphql API available at http://localhost:8082/graphql
(depending on your environment configuration).
You can define which resolvers are available in chain/src/processor/api/resolvers.ts
. By default all available resolvers generated based on your database schema file are used. You must configure additional middlewares, validations etc. yourself. The example configures a simple validation for the take
argument for resolvers returning multiple entities at once.
When deploying to a server, you should push your code along with your forked starter-kit to some repository, then clone it on your remote server and execute it.
Don't forget to run
pnpm env:sovereign docker:build
to build the required images.
# start every component with docker
pnpm env:sovereign docker:up -d
UI will be accessible at https://localhost
and GQL inspector will be available at https://localhost/graphql
(sequencer), https://localhost/indexer/graphql
(indexer) and https://localhost/processor/graphql
(processor)
Go to docker/proxy/Caddyfile
and replace the *
matcher with your domain.
yourdomain.com {
...
}
HTTPS is handled automatically by Caddy, you can (learn more about automatic https here.)[https://caddyserver.com/docs/automatic-https]
In most cases, you will need to change the NEXT_PUBLIC_PROTOKIT_GRAPHQL_URL
property in the .env
file to the domain your graphql endpoint is running in.
By default, the graphql endpoint is running on the same domain as your UI with the /graphql
suffix.
The caddy reverse-proxy automatically uses https for all connections, use this guide to remove certificate errors when accessing localhost sites
https://caddyserver.com/docs/running#local-https-with-docker
-
Make sure the framework is located under ../framework from the starter-kit's location
-
Adapt your starter-kit's package.json to use the file:// references to framework
-
Go into the framework folder, and build a docker image containing the sources with
docker build -f ./packages/deployment/docker/development-base/Dockerfile -t protokit-base .
-
Comment out the first line of docker/base/Dockerfile to use protokit-base