Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
ecae00f
chainplot: scoped onchain events to a reproducible dataset and dashboard
easeev Sep 16, 2026
e60b428
Derive rindexer's table names the way rindexer does
easeev Sep 18, 2026
4d01094
Fail publish when the URL it returns does not serve
easeev Sep 18, 2026
3f9a15c
Let serve bind beyond loopback, so the documented preview step works
easeev Sep 18, 2026
7fb22ac
init: write a .gitignore and name the project after its directory
easeev Sep 18, 2026
1f3d559
fork: drop the author's publish targets
easeev Sep 18, 2026
e53df34
Docs: say how `chainplot` gets onto PATH
easeev Sep 18, 2026
4f648cf
publish: replay a journaled success only while the release is still t…
easeev Sep 18, 2026
6fbc12a
Refuse an S3 endpoint that carries a path
easeev Sep 18, 2026
38e9bc2
CLI: register --jsonl, and answer --help without --json
easeev Sep 18, 2026
6a9d3af
Run the CLI in the container as the owner of the project
easeev Sep 18, 2026
4cca083
Gate the live e2e on a mainnet RPC, not on any RPC
easeev Sep 18, 2026
2d58b2d
Say on the dashboard whether a release can be forked, and how
easeev Sep 18, 2026
032dff2
Explain block_budget in time as well as blocks
easeev Sep 18, 2026
d5d93a4
Make the one-event export contract explicit
easeev Sep 18, 2026
23a5c16
Read DuckDB results by column, so the uniqueness gate can fire
smypmsa Sep 18, 2026
3e37d12
fork: accept a publish root remotely, as the local path already does
smypmsa Sep 18, 2026
d6b26e6
Gate the live S3 suite on whether it can run, not on a strict read
smypmsa Sep 18, 2026
79bb63b
Name snapshots the way rindexer names their tables
easeev Sep 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
node_modules
dist
coverage
.chainplot
.env
.env.*
!.env.example
.git
scripts
docs
tests
29 changes: 29 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Chainplot environment. Copy to .env and fill in. Never commit .env.
# Scope: this file is for developing Chainplot itself (live tests read it).
# For an analytics project, keep its own .env in the project directory —
# the CLI loads .env from the directory you run it in.
# All values stay local; tests and the CLI read them at runtime.

# --- Ingest (M2) ---------------------------------------------------------
# The live suites read RPC_URL (Ethereum mainnet, archive-capable). Postgres
# and rindexer come from compose, so there is no test database URL to set.
# Real analytics projects keep their own .env with per-chain endpoints.
RPC_URL=

# Postgres 16 for the rindexer adapter (compose.yaml provides one).
DATABASE_URL=postgresql://chainplot:chainplot@localhost:5432/chainplot

# --- Publish to S3-compatible storage (M4) -------------------------------
# The endpoint is an origin only — scheme and host, no path. For R2 that is
# https://<account-id>.r2.cloudflarestorage.com; the bucket goes in
# CHAINPLOT_S3_BUCKET. A path here is sent as the bucket name, so every file
# lands one level too deep and the public URL serves nothing.
CHAINPLOT_S3_ENDPOINT=
CHAINPLOT_S3_BUCKET=
CHAINPLOT_S3_REGION=auto
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=

# --- Local overrides (optional) ------------------------------------------
# rindexer binary (default: rindexer on PATH)
# CHAINPLOT_RINDEXER_BIN=
104 changes: 104 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
name: Build & Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

- uses: pnpm/action-setup@v6
with:
version: 11.24.0

- uses: actions/setup-node@v7
with:
node-version: 22
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

# The viewer is a separate project with its own lockfile. Typecheck it
# explicitly: `vite build` does not, so a type error here would
# otherwise ship in the bundle every release embeds.
- name: Install viewer dependencies
run: pnpm --dir viewer install --frozen-lockfile

- name: Typecheck viewer
run: pnpm --dir viewer run typecheck

- name: Build CLI and viewer
run: pnpm build

- name: Run tests
run: pnpm vitest run

template-smoke:
name: Scaffolded template runs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

- uses: pnpm/action-setup@v6
with:
version: 11.24.0

- uses: actions/setup-node@v7
with:
node-version: 22
cache: pnpm

- name: Install dependencies
run: |
pnpm install --frozen-lockfile
pnpm --dir viewer install --frozen-lockfile

- name: Build CLI and viewer
run: pnpm build

# The producer image is the CLI plus rindexer, which ships linux/amd64
# only. Every step below is what a user does from the template README;
# each of them was broken at some point and none was covered by a test.
- name: Build the producer image
run: |
docker build --platform linux/amd64 -t chainplot:local \
-f docker/producer.Dockerfile .

- name: Scaffold the template
run: |
node dist/cli/main.js init --template ingest-transfers \
--output "$RUNNER_TEMP/proj" --json

# No RPC is needed to prove the stack comes up and the CLI is reachable.
- name: Bring the stack up and drive the CLI
working-directory: ${{ runner.temp }}/proj
run: |
printf 'RPC_URL=http://127.0.0.1:1\n' > .env
docker compose up -d
docker compose ps
docker compose exec -T producer chainplot capabilities --json
docker compose exec -T producer chainplot validate --json

# The container writes into the bind-mounted project as its owner, not as
# root, so a build run inside it leaves files the host user can read and
# delete without sudo. The fixture template builds offline.
- name: Files the container writes belong to the host user
working-directory: ${{ runner.temp }}/proj
run: |
docker compose exec -T producer chainplot init \
--template fixture-transfers --output /workspace/fx --json
docker compose exec -T -w /workspace/fx producer chainplot build --json
test -O fx/dist/releases/local/release.json
rm -rf fx

- name: Tear down
if: always()
working-directory: ${{ runner.temp }}/proj
run: docker compose down -v
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
node_modules/
/dist/
examples/**/dist/
.chainplot/
.worktrees/
.superpowers/
.env
.env.*
!.env.example
*.log
.DS_Store
coverage/
.pnpm-store/
.vitest/
viewer/node_modules
# Built from viewer/src by `pnpm build`; committing it lets the two drift.
viewer/dist/
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Chainstack Labs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
21 changes: 21 additions & 0 deletions NOTICES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Upstream notices

Chainplot is MIT-licensed (see `LICENSE`). It bundles or depends on the
following upstream software at runtime; their licenses govern those
components, not the datasets you publish.

| Component | License | Use |
|---|---|---|
| [rindexer](https://github.com/joshstevens19/rindexer) | MIT (pinned binary from the upstream image) | EVM event indexing |
| [DuckDB](https://duckdb.org) via `@duckdb/node-api` | MIT | Snapshot queries and Parquet export |
| [React](https://react.dev) | MIT | Viewer |
| [ECharts](https://echarts.apache.org) | Apache-2.0 | Viewer charts |
| [AWS SDK for JavaScript v3](https://github.com/aws/aws-sdk-js-v3) | Apache-2.0 | S3-compatible publish |
| [pg](https://github.com/brianc/node-postgres) | MIT | Advisory lock, coverage cursor reads |
| [ajv](https://github.com/ajv-validator/ajv), [yaml](https://github.com/eemeli/yaml), [commander](https://github.com/tj/commander.js), [Vite](https://vitejs.dev) | MIT | Schema validation, YAML, CLI, viewer build |

## Dataset licenses are separate

The software license (MIT) does not cover the data you publish. Every publish
target requires an explicit `dataset_license` field; it is recorded with the
release. Choose and document the license that applies to your dataset.
Loading
Loading