4.2 KiB
Overview: Why the Memo Indexer Exists
The problem
The Memo protocol encodes social actions—posts, replies, likes, follows, profiles, topics—in Bitcoin Cash transactions using OP_RETURN outputs. Wallets and explorers can read individual transactions from a full node, but useful applications need:
- A queryable history of who posted what, when, and in reply to which parent transaction
- Derived indexes (follow graph, likes per post, topic membership) without re-scanning the entire chain on every API request
- Consistent interpretation of Memo action bytes (
0x6dprefix + action code) across services
Scanning the blockchain on demand for every user request does not scale. The Memo indexer exists to materialize protocol state into local databases so other apps (APIs, analytics, mirrors) can read indexed data quickly.
What this stack does
Two cooperating Node.js services mirror the proven PSF pattern used for SLP tokens:
BCH full node (RPC + ZMQ)
│
▼
┌───────────────────────┐ HTTP REST ┌─────────────────┐
│ psf-memo-indexer │ ─────────────────► │ psf-memo-db │
│ (2 processes) │ /level/* │ (LevelDB) │
└───────────────────────┘ └─────────────────┘
│ │
│ ▼
│ Query / backup APIs
▼
Memo OP_RETURN txs
from blocks + mempool
psf-memo-indexer watches the chain, detects Memo transactions, validates action payloads, and writes structured records.
psf-memo-db owns storage. It exposes CRUD over multiple LevelDB instances so the indexer (and future tools) do not open database files directly—avoiding lock contention and allowing backup/restore as a separate concern.
What v1 indexes
The JavaScript indexer intentionally matches the core social handlers registered in the reference Go indexer’s op_return package—not the full Memo protocol spec:
| Indexed in v1 | Not indexed in v1 |
|---|---|
Set name (0x6d01) |
Polls (0x6d10–0x6d14) |
Post (0x6d02) |
Mute / unmute |
Reply (0x6d03) |
Send money (0x6d24) |
Like (0x6d04) |
Token sale MIP-0009 actions |
Set profile (0x6d05) |
SLP / Bitcom OP_RETURN in Go indexer |
Follow / unfollow (0x6d06 / 0x6d07) |
Planned spec actions (0x6d08, 0x6d0b, …) |
Set profile picture (0x6d0a) |
|
Topic message / follow / unfollow (0x6d0c–0x6d0e) |
See design-decisions-and-tradeoffs.md for rationale.
Start height
Indexing begins at block 525000 (BeginningOfMemoHeight in the Go reference). Earlier blocks are skipped because Memo activity before that height is negligible for practical deployments.
Who consumes the output
This repository does not ship a GraphQL or public REST API for end users—that exists in the separate memo/index Go project. PSF’s stack is an indexer + DB layer intended for:
- PSF infrastructure that wants Memo data beside SLP indexing patterns
- Custom services that call
psf-memo-dbREST endpoints - Future query layers (e.g. a slim
memo-querymodule) without reimplementing chain scanning
Operational summary
| Process | Entry point | When it runs |
|---|---|---|
| Block indexer | psf-memo-block-indexer.js |
IBD from START_BLOCK_HEIGHT to chain tip; then ZMQ rawblock |
| TX indexer | psf-memo-tx-indexer.js |
After block indexer calls GET /tx-start; then ZMQ rawtx |
| Database | psf-memo-db index.js |
Must be running before indexers start |
Typical development:
# Terminal 1
cd psf-memo-db && npm start
# Terminal 2
cd psf-memo-indexer && npm run block-indexer
# Terminal 3
cd psf-memo-indexer && npm run tx-indexer
Production uses production/docker with the same three logical services.