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

Commit 2025bf6

Browse files
chunter-cbclaude
andcommitted
feat: vibenet stack — faucet, explorer, landing page (Next.js port)
Ports the vibenet Rust/nginx stack to this Next.js app: - Landing page (/) with chain info, features, contracts - Faucet page + API routes (/faucet, /api/vibenet/faucet/*) using viem for signing, in-memory rate limiting per IP/address - Block explorer pages + API routes (/explorer/*, /api/vibenet/explorer/*) backed by better-sqlite3 (same schema as vibescan Rust crate) - Background indexer script (scripts/indexer.mjs) that backfills and subscribes to newHeads via WebSocket - Subdomain routing via proxy.ts: faucet.vibes.base.org → /faucet, explorer.vibes.base.org → /explorer - TIPS pages moved to /tips to free up root for vibenet landing - Dockerfile updated: self-contained build context, starts both Next.js server and background indexer Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent 0d1b3ab commit 2025bf6

32 files changed

Lines changed: 6785 additions & 749 deletions

File tree

Dockerfile

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
FROM oven/bun:1 AS deps
22
WORKDIR /app
3-
COPY ui/package.json ui/bun.lock ./
3+
COPY package.json bun.lock ./
44
RUN bun install --frozen-lockfile
55

66
FROM oven/bun:1 AS builder
77
WORKDIR /app
88
COPY --from=deps /app/node_modules ./node_modules
9-
COPY ./ui .
9+
COPY . .
1010

1111
ENV NEXT_TELEMETRY_DISABLED=1
1212

@@ -21,12 +21,16 @@ ENV NEXT_TELEMETRY_DISABLED=1
2121
RUN addgroup --system --gid 1001 nodejs
2222
RUN adduser --system --uid 1001 nextjs
2323

24-
RUN mkdir .next
25-
RUN chown nextjs:nodejs .next
24+
RUN mkdir -p .next /data
25+
RUN chown nextjs:nodejs .next /data
2626

2727
COPY --from=builder /app/public ./public
2828
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
2929
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
30+
COPY --from=builder /app/scripts ./scripts
31+
COPY --from=builder /app/docker/migrations ./docker/migrations
32+
33+
RUN chmod +x scripts/start.sh
3034

3135
USER nextjs
3236

@@ -35,4 +39,4 @@ EXPOSE 3000
3539
ENV PORT=3000
3640
ENV HOSTNAME="0.0.0.0"
3741

38-
CMD ["node", "server.js"]
42+
CMD ["sh", "scripts/start.sh"]

docker/migrations/0001_init.sql

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
-- vibescan indexer schema (ported from crates/vibenet/explorer).
2+
-- Everything derivable from RPC stays in the node; the only persisted state
3+
-- is the cursor + the address-activity join index that plain JSON-RPC cannot
4+
-- serve efficiently.
5+
6+
CREATE TABLE IF NOT EXISTS cursor (
7+
id INTEGER PRIMARY KEY CHECK (id = 0),
8+
last_indexed_block INTEGER NOT NULL,
9+
last_indexed_hash TEXT NOT NULL,
10+
updated_at INTEGER NOT NULL
11+
);
12+
13+
CREATE TABLE IF NOT EXISTS blocks (
14+
number INTEGER PRIMARY KEY,
15+
hash TEXT NOT NULL UNIQUE,
16+
timestamp INTEGER NOT NULL,
17+
miner TEXT NOT NULL,
18+
tx_count INTEGER NOT NULL,
19+
gas_used INTEGER NOT NULL,
20+
gas_limit INTEGER NOT NULL,
21+
base_fee TEXT
22+
);
23+
24+
CREATE TABLE IF NOT EXISTS txs (
25+
hash TEXT PRIMARY KEY,
26+
block_num INTEGER NOT NULL,
27+
tx_index INTEGER NOT NULL,
28+
from_addr TEXT NOT NULL,
29+
to_addr TEXT,
30+
value TEXT NOT NULL,
31+
status INTEGER NOT NULL,
32+
created TEXT
33+
);
34+
CREATE INDEX IF NOT EXISTS idx_txs_block_num ON txs (block_num DESC, tx_index DESC);
35+
36+
-- address -> activity feed. role values:
37+
-- 0 = sender, 1 = recipient, 2 = creator
38+
-- 3 = erc20/721 log from, 4 = erc20/721 log to
39+
CREATE TABLE IF NOT EXISTS address_activity (
40+
address TEXT NOT NULL,
41+
block_num INTEGER NOT NULL,
42+
tx_index INTEGER NOT NULL,
43+
log_index INTEGER NOT NULL DEFAULT -1,
44+
tx_hash TEXT NOT NULL,
45+
role INTEGER NOT NULL,
46+
token TEXT,
47+
PRIMARY KEY (address, block_num, tx_index, log_index, role)
48+
);
49+
CREATE INDEX IF NOT EXISTS idx_activity_addr_block
50+
ON address_activity (address, block_num DESC, tx_index DESC, log_index DESC);
51+
52+
CREATE TABLE IF NOT EXISTS addresses (
53+
address TEXT PRIMARY KEY
54+
);
55+
56+
CREATE TABLE IF NOT EXISTS explorer_stats (
57+
id INTEGER PRIMARY KEY CHECK (id = 0),
58+
blocks INTEGER NOT NULL,
59+
txs INTEGER NOT NULL,
60+
addresses INTEGER NOT NULL
61+
);
62+
63+
INSERT INTO explorer_stats (id, blocks, txs, addresses)
64+
VALUES (0, 0, 0, 0)
65+
ON CONFLICT(id) DO NOTHING;

docker/vibenet-env.example

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# base/ui vibenet env — UI-specific config only.
2+
# Infra secrets (chain IDs, faucet key, etc.) live in base/base etc/vibenet/vibenet-env.
3+
# This file is passed as a second --env-file to docker compose and merges with it.
4+
5+
# === Explorer ===
6+
VIBESCAN_DB_PATH=/data/vibescan.db
7+
VIBESCAN_START_BLOCK=0
8+
VIBESCAN_BACKFILL_CONCURRENCY=16
9+
10+
# === Optional: surfaced in explorer footer ===
11+
# VIBESCAN_PUBLIC_RPC_URL=https://rpc.vibes.base.org
12+
# VIBESCAN_PUBLIC_FAUCET_URL=https://faucet.vibes.base.org

next.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import type { NextConfig } from "next";
22

33
const nextConfig: NextConfig = {
44
output: "standalone",
5+
// better-sqlite3 is a native module; exclude it from webpack bundling
6+
serverExternalPackages: ["better-sqlite3"],
57
};
68

79
export default nextConfig;

0 commit comments

Comments
 (0)