npm package: @simplepg/node
Description: JavaScript implementation of the SimplePage backend service
Author: Joel Thorstensson
Latest version: 1.5.0

# SimplePage Node

A decentralized backend service for the SimplePage application that provides IPFS storage, blockchain indexing, and REST API endpoints for managing decentralized web pages.

## Overview

SimplePage Node is a Node.js service that bridges the gap between the SimplePage smart contract and IPFS storage. It provides:

- **IPFS Integration**: Upload, retrieve, and manage CAR (Content Addressable aRchive) files
- **Blockchain Indexing**: Monitor SimplePage contract events and track ENS contenthash updates
- **REST API**: HTTP endpoints for page operations with automatic Swagger documentation
- **List Management**: Allow/block list functionality for ENS domains
- **Content Finalization**: Automatic staging and finalization of page content

## Features

### 🗄️ IPFS Storage
- Upload CAR files with automatic pinning and staging
- Retrieve page content with optimized CAR file generation
- Content finalization based on blockchain events
- Automatic cleanup of old staged content

### ⛓️ Blockchain Indexing
- Monitor SimplePage contract for new page registrations
- Track ENS contenthash updates for registered domains
- Maintain synchronized state between blockchain and IPFS
- Support for multiple blockchain networks

### 🌐 REST API
- Upload new pages with domain association
- Retrieve page content by CID
- Automatic OpenAPI/Swagger documentation
- File upload support with multipart/form-data

### 📋 List Management
- Allow list management for trusted domains
- Block list management for restricted domains
- CLI commands for list operations
- Persistent storage using IPFS pins

## Installation

### Prerequisites

- Node.js 20+ with ES modules support
- IPFS node (Kubo) running and accessible
- Ethereum RPC endpoint

### Install

```bash
pnpm add -g @simplepg/node
```

## Usage

### Command Line Interface

The Node provides a CLI with various options and subcommands:

```bash
# Start the service with default settings
simplepage-node

# Start with custom configuration
simplepage-node \
  --ipfs-api http://localhost:5001 \
  --api-port 3000 \
  --api-host localhost \
  --rpc https://mainnet.infura.io/v3/YOUR_KEY \
  --start-block 18000000 \
  --chain-id 1

# Manage allow list
simplepage-node allow-list show
simplepage-node allow-list add example.eth
simplepage-node allow-list rm example.eth

# Manage block list
simplepage-node block-list show
simplepage-node block-list add spam.eth
simplepage-node block-list rm spam.eth
```

## Configuration

### Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `IPFS_API_URL` | IPFS API endpoint | `http://localhost:5001` |
| `API_PORT` | HTTP API port | `3000` |
| `API_HOST` | HTTP API host | `localhost` |
| `RPC_URL` | Ethereum RPC URL | `http://localhost:8545` |
| `START_BLOCK` | Starting block for indexing | `1` |
| `CHAIN_ID` | Ethereum chain ID | `1` |

### Command Line Options

| Option | Short | Description | Default |
|--------|-------|-------------|---------|
| `--ipfs-api` | `-i` | IPFS API URL | `http://localhost:5001` |
| `--api-port` | `-p` | API port | `3000` |
| `--api-host` | `-a` | API host | `localhost` |
| `--rpc` | `-r` | Ethereum RPC URL | `http://localhost:8545` |
| `--start-block` | `-b` | Starting block number | `1` |
| `--chain-id` | `-c` | Chain ID | `1` |
| `--disable-provide` |  | Disable IPFS provide on finalize | `false` |
| `--disable-peer-discovery` |  | Disable IPFS DHT peer discovery | `false` |


## API Reference

### Base URL
```
http://localhost:3000
```

### Endpoints

#### GET /page
Retrieve a page by its CID. Returns a CAR-file containing only index.html and index.md files for each directory contained by the page.

**Query Parameters:**
- `cid` (required): Content identifier of the page

**Response:**
- `200`: CAR file containing the page data
- `400`: Bad request (missing CID)
- `404`: Page not found

**Example:**
```bash
curl "http://localhost:3000/page?cid=bafybeieffej45qo3hqi3eggqoqwgjihscmij42hmhqy3u7se7vzgi7h2zm"
```

#### POST /page
Upload a new page.

**Query Parameters:**
- `domain` (required): ENS domain for the page

**Body:**
- `file` (required): CAR file (application/vnd.ipld.car)

**Response:**
```json
{
  "cid": "bafybeieffej45qo3hqi3eggqoqwgjihscmij42hmhqy3u7se7vzgi7h2zm"
}
```

**Example:**
```bash
curl -X POST \
  -F "file=@page.car" \
  "http://localhost:3000/page?domain=example.eth"
```

#### GET /info
Get API version information.

**Response:**
```json
{
  "version": "0.1.0"
}
```

#### GET /docs
Interactive API documentation (Swagger UI).

#### GET /openapi.json
OpenAPI specification in JSON format.

## Architecture

### Services

#### IpfsService
Handles all IPFS-related operations:
- CAR file upload and retrieval
- Content pinning and staging
- List management using IPFS pins
- Content finalization

#### IndexerService
Manages blockchain indexing:
- Monitors SimplePage contract events
- Tracks ENS contenthash updates
- Synchronizes blockchain state with IPFS 
- Retrieves page data from other nodes over IPFS
- Handles page finalization triggers

#### API Service
Provides HTTP endpoints:
- RESTful API for page operations
- Automatic OpenAPI documentation
- File upload handling
- Error handling and validation

### Data Flow

1. **Page Upload**: Client uploads CAR file → IPFS storage → Staged pin created
2. **Blockchain Event**: Indexer detects new page registration → Domain added to list
3. **Contenthash Update**: Indexer detects ENS contenthash change → CID tracked
4. **Finalization**: Indexer triggers content finalization → Staged pin → Final pin
5. **Retrieval**: Client requests page → Optimized CAR file generated and served

## Development

### Running Tests

```bash
# Run all tests
pnpm test

# Run specific test file
npm test -- tests/services/ipfs.test.js
```

### Development Mode

```bash
# Start with auto-restart on file changes
pnpm run dev
```

### Linting

```bash
# Run ESLint
pnpm run lint
```

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests for new functionality
5. Ensure all tests pass
6. Submit a pull request

## License

MIT License - see [LICENSE](../../LICENSE) for details.

## Support

For questions and support:
- Open an issue on GitHub