typeblock is an educational proof-of-stake blockchain node written in TypeScript. It includes a UTXO transaction model, secp256k1 wallet keys, a transaction pool, block validation, peer-to-peer syncing over WebSocket, an HTTP API, and a small browser UI.
The project started from Sandoche's NaivecoinStake and the accompanying tutorial. This version keeps the learning scope but restructures the code around stricter TypeScript, runtime validation, tests, and clearer module boundaries.
This is not production blockchain software. Do not use it for real funds, real identities, or internet-exposed consensus experiments.
- Proof-of-stake block minting with deterministic block and transaction hashing.
- UTXO-based transactions, coinbase rewards, wallet signing, and transaction pool validation.
- Chain replacement validation with UTXO rebuilds, fork-choice checks, and transaction pool pruning.
- Runtime validation for HTTP bodies, peer URLs, P2P messages, blocks, and transactions.
- Peer-to-peer block and transaction-pool broadcasting over
ws://orwss://. - Browser UI for blocks, wallet state, peers, UTXOs, pending transactions, minting, and lookup.
- CI-friendly tooling: strict TypeScript, ESLint, Prettier, Vitest, and build output declarations.
- Node.js 20.19+
- npm
The simplest way to start:
npm run devOpen the UI:
http://localhost:3001
If you want to run from compiled output:
npm run build
npm startStart the first node:
npm run devStart a second node in another terminal:
HTTP_PORT=3002 P2P_PORT=6002 PRIVATE_KEY=node/wallet/private_key_2 npm run devConnect the second node to the first:
curl -X POST http://localhost:3002/addPeer \
-H 'content-type: application/json' \
-d '{"peer":"ws://localhost:6001"}'You can also connect nodes from the browser UI by opening the second node at
http://localhost:3002 and submitting ws://localhost:6001 in the peer form.
Wallet keys are generated locally under node/wallet/private_key* and ignored by Git. Delete an
ignored key file if you want that local node to generate a new wallet.
| Variable | Default | Description |
|---|---|---|
HTTP_PORT |
3001 |
HTTP API and browser UI port |
P2P_PORT |
6001 |
WebSocket peer-to-peer port |
PRIVATE_KEY |
node/wallet/private_key |
Wallet private-key file path |
LOG_LEVEL |
info |
debug, info, warn, or error |
ENABLE_STOP_ENDPOINT |
unset | Set to true to enable POST /stop |
Invalid ports and log levels fail startup with a clear error.
| Method | Path | Description |
|---|---|---|
GET |
/blocks |
List blocks |
GET |
/wallet |
Show local wallet address, balance, and UTXOs |
GET |
/transactionPool |
List pending transactions |
GET |
/peers |
List connected peers |
GET |
/transaction/:id |
Find a transaction by id |
GET |
/address/:address |
Show current balance and UTXOs for an address |
POST |
/mintBlock |
Mint a block with the current transaction pool |
POST |
/mintRawBlock |
Mint a block from supplied transaction data |
POST |
/mintTransaction |
Mint a block containing one wallet transaction |
POST |
/sendTransaction |
Add one wallet transaction to the pool and broadcast it |
POST |
/addPeer |
Connect to a ws:// or wss:// peer |
POST |
/stop |
Stop the process when ENABLE_STOP_ENDPOINT=true |
Historical address lookup:
GET /address/:address?height=123
Transaction request body for /mintTransaction and /sendTransaction:
{
"address": "04...",
"amount": 10
}Raw block request body for /mintRawBlock:
{
"data": []
}Peer request body for /addPeer:
{
"peer": "ws://localhost:6001"
}src/
chain/ blocks, blockchain state, consensus, validation
crypto/ canonical serialization and hashing
net/ HTTP server, P2P server, wire-message validation
tx/ transactions, UTXOs, transaction pool, validation
util/ logger
wallet/ key management, balances, transaction creation
public/ browser UI served by the node
test/ Vitest coverage for core behavior and API boundaries
npm run typecheck
npm run lint
npm run format:check
npm test
npm run buildUseful scripts:
| Script | Description |
|---|---|
npm run dev |
Run src/main.ts in watch mode |
npm run build |
Compile TypeScript to dist |
npm start |
Run dist/main.js |
npm test |
Run the test suite |
npm run test:watch |
Run Vitest in watch mode |
npm run lint |
Run ESLint |
npm run lint:fix |
Run ESLint with fixes |
npm run format:check |
Check Prettier formatting |
npm run format |
Format files with Prettier |
MIT