Skip to content
This repository was archived by the owner on Feb 5, 2026. It is now read-only.

gufranco/blockchain-fundamentals

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Blockchain Fundamentals

A blockchain implementation demonstrating DDD, SOLID, KISS, DRY, and Clean Code principles.

Quick Start

nvm use
pnpm install
pnpm start

Architecture

src/
├── domain/
│   ├── aggregates/
│   │   └── blockchain.aggregate.js
│   ├── entities/
│   │   └── block.entity.js
│   ├── errors/
│   │   ├── domain.error.js
│   │   ├── validation.error.js
│   │   └── blockchain.error.js
│   ├── services/
│   │   └── hash.service.js
│   └── value-objects/
│       ├── hash.value-object.js
│       └── timestamp.value-object.js
│
└── infrastructure/
    └── services/
        └── sha256-hash.service.js

File Naming Convention

Pattern Example Description
name.entity.js block.entity.js DDD Entity (has identity)
name.value-object.js hash.value-object.js DDD Value Object (immutable)
name.aggregate.js blockchain.aggregate.js DDD Aggregate Root
name.service.js hash.service.js Service (domain or infrastructure)
name.error.js validation.error.js Custom Error Class

Principles

SOLID

Principle Application
S - Single Responsibility Each class has one job
O - Open/Closed HashService is extensible without modification
L - Liskov Substitution Any HashService implementation can replace another
I - Interface Segregation Small interfaces (hash(), verify())
D - Dependency Inversion Domain depends on abstractions

DDD Patterns

Pattern Implementation
Entity Block - unique identity (hash)
Value Object Hash, Timestamp - immutable, compared by value
Aggregate Root Blockchain - manages consistency
Domain Service HashService - stateless operation
Domain Error Exception hierarchy

Clean Code

  • Meaningful names
  • Small, focused methods
  • Direct imports (no barrel exports)
  • Proper exception hierarchy

Usage

Basic

import { Blockchain } from './src/domain/aggregates/blockchain.aggregate.js';
import { Sha256HashService } from './src/infrastructure/services/sha256-hash.service.js';

const blockchain = new Blockchain(new Sha256HashService());

blockchain.addBlock({ from: 'Alice', to: 'Bob', amount: 100 });
blockchain.addBlock('Hello, Blockchain!');

console.log(blockchain.isValid());
blockchain.dump();

Custom Hash Service

import { HashService } from './src/domain/services/hash.service.js';
import { Blockchain } from './src/domain/aggregates/blockchain.aggregate.js';

class CustomHashService extends HashService {
  hash(data) {
    return '0'.repeat(64);
  }
}

const blockchain = new Blockchain(new CustomHashService());

Imports

// Aggregate
import { Blockchain } from './src/domain/aggregates/blockchain.aggregate.js';

// Entity
import { Block } from './src/domain/entities/block.entity.js';

// Value Objects
import { Hash } from './src/domain/value-objects/hash.value-object.js';
import { Timestamp } from './src/domain/value-objects/timestamp.value-object.js';

// Services
import { HashService } from './src/domain/services/hash.service.js';
import { Sha256HashService } from './src/infrastructure/services/sha256-hash.service.js';

// Errors
import { DomainError } from './src/domain/errors/domain.error.js';
import { ValidationError } from './src/domain/errors/validation.error.js';
import { BlockchainError } from './src/domain/errors/blockchain.error.js';

API

Blockchain

// Properties
blockchain.length        // Number of blocks
blockchain.genesisBlock  // First block
blockchain.latestBlock   // Last block

// Methods
blockchain.addBlock(data)           // Add new block, returns Block
blockchain.getBlock(index)          // Get block by index (-1 = last)
blockchain.findBlock(predicate)     // Find first matching block
blockchain.findBlocks(predicate)    // Find all matching blocks
blockchain.validate()               // Returns { valid: boolean, errors: string[] }
blockchain.isValid()                // Returns boolean
blockchain.toJSON(indent?)          // Serialize to JSON string
blockchain.toArray()                // Convert to plain objects array
blockchain.dump(options?)           // Print to console
blockchain.entries()                // Returns iterator with [index, block]

// Iteration
for (const block of blockchain) { }

Block

// Properties (read-only)
block.index        // Position in chain
block.previousHash // Hash value object
block.data         // Stored data
block.timestamp    // Timestamp value object
block.hash         // Hash value object
block.isGenesis    // Boolean

// Methods
block.isHashValid()   // Verify hash integrity
block.calculateHash() // Recalculate hash
block.toObject()      // Convert to plain object

// Static
Block.fromObject(obj, hashService)  // Reconstruct from plain object

Hash

// Static
Hash.LENGTH   // 64
Hash.GENESIS  // Genesis block's previous hash (64 zeros)
Hash.PATTERN  // Validation regex

// Instance
hash.value          // String value
hash.equals(other)  // Compare with another Hash
hash.toString()     // String representation
hash.toJSON()       // For JSON serialization

Timestamp

// Static
Timestamp.now()  // Create current timestamp

// Instance
timestamp.value  // ISO 8601 string
timestamp.date   // Date object (copy)
timestamp.equals(other)
timestamp.isBefore(other)
timestamp.isAfter(other)
timestamp.toString()
timestamp.toJSON()

HashService

// Abstract methods
hashService.hash(data)                  // Returns hash string
hashService.verify(data, expectedHash)  // Returns boolean

Errors

// DomainError (base)
error.message  // Error message
error.code     // Error code
error.name     // Class name

// ValidationError extends DomainError
error.field    // Field that failed validation

// BlockchainError extends DomainError
error.blockIndex  // Problematic block index

Demo Output

The app.js demo generates fake data using @faker-js/faker:

  • User registrations
  • Cryptocurrency transactions (BTC, ETH, SOL, etc.)
  • Document verifications
  • NFT mints
  • Smart contract deployments

Each run produces different data.

Requirements

  • Node.js 20+

License

MIT

Author

Gustavo Franco - gustavocfranco@gmail.com - @gufranco

About

Educational blockchain implementation demonstrating DDD, SOLID, and Clean Architecture principles

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors