Page MenuHomePhabricator

[metachronik, charts.e.cash] A new analytics-focused indexer and a charting front end for visualizing its data
ClosedPublic

Authored by bytesofman on Jul 1 2025, 13:56.

Details

Summary

Note: This was built using cursor, so the code itself is almost entirely AI-generated.

Features

metachronik
A nodejs app that starts up and indexes a database using chronik. The schema is defined in the server. The server will determine chaintip and begin populating the database on startup. If the database is populated through the chaintip, the server will listen for finalized blocks and add them as they come in. The server runs a cron job to fill in any blocks that may have been missed by the websocket.

The server is a standalone app and interacts only with a database. It does not expose an API and the charts front end does not interact directly with the server. The charts frontend connects directly to the database (it is a nextjs app, so it runs effectively it's own server that runs an API populated by the same database that is updated by the indexer).

Front end
NextJS app that visually presents network activity overtime, according to the database schema. User can select different time windows. User can zoom to select different y-axis max values. The BCH and XEC forks are marked with reference lines. We include some novel data that probably would not make sense to index with chronik, like volume over time. Perhaps it would be better to come up with a more extensive chronik plugin, or add more volume data to the existing agora plugin. But we will probably always have some data that really is only interesting for charting purposes. Charts are mobile responsive.

Everything in this diff is deployed. The database is being updated by the indexer. The front-end is deployed and connected to the database. We could launch this just by moving the domain -- we could also keep the existing stack and support CI. Would be a bit of an infra change for ABC, but could be the way to go if we are going to have lots of nextjs apps and one-off backends where a dedicated server is arguably overkill.

https://charts-e-cash.vercel.app/

Data that is charted is available at public API endpoints, e.g.: https://charts-e-cash.vercel.app/api/charts/daily-stats?start_date=2024-07-10&end_date=2025-07-10

Test Plan

See README for running instructions.

Otherwise best test is reviewing https://charts-e-cash.vercel.app/

test the Dockerfiles:

docker build -f charts.e.cash.Dockerfile -t charts_e_cash_local .
docker build -f metachronik.Dockerfile -t metachronik_local .

I will configure teamcity to pass the correct env vars to the docker files for deploy

the front end is live at charts.e.cash

Diff Detail

Repository
rABC Bitcoin ABC
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

bytesofman edited the test plan for this revision. (Show Details)

init db without a script, lint

bytesofman published this revision for review.Jul 1 2025, 14:13
bytesofman edited the summary of this revision. (Show Details)

thinking about this, it's in a good state for testing and dev iteration. no need to land it and iterate through lots of refactors and schema changes.

keep iterating until we have something tested that could be useful to users / launch as a site.

frontend is headless nextjs app, API calls all local from db connection. backend is not an express server, only an indexer. script for price updates.

  • sanity check scan for AI copypasta problems
  • figure out CI / deployment plan
  • add any missing tests

lint, improve chart speed with individual API routes, better type checking, better responsiveness, use latest version of recharts, better fork ref lines

Still needs some more pre-review for AI-related copy pasta and hiccups, esp on the indexer side.

But coming along nicely, can check it out at https://charts-e-cash.vercel.app/

lint chronik-charts, remove dead code, use this version in live test-prod deployment

bytesofman edited the test plan for this revision. (Show Details)

update readme, remove railway dep file

.cursorrules
1 ↗(On Diff #54734)

this file is not directly related to this diff, but it is useful to add some cursor rules for working with this specific monorepo.

for now this is just some boilerplate stuff based on what I've seen so far. Would be expected to evolve. Should be in the monorepo at the top level, only relevant for cursor users

29 ↗(On Diff #54734)

AI really wants 8 decimal places here

I have lots of questions, let's start with a couple of the main ones:

  • What is the purpose of the cron and the reconciliation thing, why is there several data gathering methods (ws, cron, reconciliation) ?
  • How would you plug a new chart/data collection to this ?

I have lots of questions, let's start with a couple of the main ones:

  • What is the purpose of the cron and the reconciliation thing, why is there several data gathering methods (ws, cron, reconciliation) ?

It was added when I was doing initial indexing to ensure the initial indexing was not skipping rows. The initial indexing involved so many API calls and iterative run-ups against memory limits that I had to do this a few times, and it was worth just having it automated. At this point in the codebase, I do not think it is necessary for the initial indexing (if the server crashes, it corrects on restart) -- but since the primary way of continuing to index is websockets, there should be some kind of system that handles a missed websocket msg.

In practice I have not seen any missed websocket msgs. But the check is not expensive and does make everything more robust.

The issue causing row skipping crashes during initial indexing -- making API calls based on number of blocks, not on number of txs in those blocks, and then crashing when X number of blocks has way more txs than expected -- is solved; we now query for next blocks based on a capped number of txs.

  • How would you plug a new chart/data collection to this ?
  1. Add a new column to the db
  2. Update the schema in the codebase to match
  3. Develop a system to index empty columns that are not price in the background (i.e. websockets add new rows with all data, a routine is indexing empty columns with chronik calls until we have data for all blocks)
  4. On indexing complete, modify the front end to chart the new data

Step 3 is doing a lot of lifting here. But, since all of the data comes from chronik calls, I don't think it would be too difficult. I think type of approach would be easier / less downtime than a full reindex of all data, tho that would also work. I can imagine some things may require a full reindex, but in that event we could just plug a new instance to a new db, wait for it to index, then switch the charts front end to the new db with the new columns.

improve x-axis tick resolution (update on chart switch), improve miner rewards chart so we do not show 0 values

remove pinch to zoom, which does not work as most mobile browsers use pinch to zoom for the whole page

change name chronik-charts to metachronik

bytesofman retitled this revision from [chronik-charts] Init charting indexer and front end to [metachronik, charts.e.cash] A new analytics-focused indexer and a charting front end for visualizing its data.Jul 10 2025, 19:31
bytesofman edited the summary of this revision. (Show Details)
bytesofman edited the test plan for this revision. (Show Details)

Recommended path forward here

  • Test the charts app at https://charts-e-cash.vercel.app/ and recommend any launch-critical changes
  • Review metachronik as an analytics (non-financial, non-critical, kind of experimental) app.

metachronik is mostly AI-generated, but the indexing components are tested (i.e. how we go from typed chonik responses to the data we want to store). It is not a speed-optimized indexer. I plan to add many new and potentially time-consuming columns to this database. I will modify the codebase so that new columns can be added "in the background," i.e. without impacting existing columns in the database.

Leveraging AI will be able dramatically increase the pace of iterations. I think that this type of system is appropriate for this type of product, which otherwise never would have been built.

I'm also not really sure what the alternative would be like. So much about how the indexer is designed depends on what we want to index. We do not know exactly what we want to index yet, this is expected to be dynamic. It seems pretty wild to have a "fluid" indexer. But for an experimental / analytics-focused meta indexer...why not? The database is not expected to be fluid. As our schema matures, we will have a better time optimizing for indexing itself.

  • Keep the current deployment infra
  • Charts is currently deployed on vercel free tier. we could bump it if / when we have a traffic problem. Vercel is capable of handling custom domains, so we could launch this at charts.e.cash, or any other domain
  • metachronik is currently deployed on https://railway.com/ hobby tier ($5/month). It's hard to say what kind of server demands we will have with this app. Easy to scale and iterate rapidly on something like railway.
  • the database is at neon.tech ($20/month). We could host our own db for this, but the neon front end is pretty useful, especially when dealing with expected troubleshooting, bugs, other unforeseen issues involved in working out new columns. it's easy to link a nextjs app or a railway indexer to a postgresql database on neon.

vercel and railway both support CI deployments, so we could still automate deployments through teamcity.

add cumulative faucet chart, improve organization of chart info, improve maintainability of scroll zoom, update schema with new view

add better meta info, twitter card, google analytics, and env.example template for env vars

Klakurka requested changes to this revision.Jul 11 2025, 04:53
Klakurka added a subscriber: Klakurka.

Different issues but there's a problem with the 'Price Data' page 'All Time' (showing pricing pre-2020) and 'BCH' (showing wrong pricing) filters.

This revision now requires changes to proceed.Jul 11 2025, 04:53

add indexing wishlist, special rendering for the mining rewards area chart so we do not show ifp pre xec

There are still some axis issues in the charts. Example: open the block size chart and unzoom: the axis go very large and you can't zoom back to an appropriated scale without reseting

Different issues but there's a problem with the 'Price Data' page 'All Time' (showing pricing pre-2020) and 'BCH' (showing wrong pricing) filters.

should be patched now

There are still some axis issues in the charts. Example: open the block size chart and unzoom: the axis go very large and you can't zoom back to an appropriated scale without reseting

patched

in this case, specific issue related to this chart -- the database has this value in bytes, but we are transforming it to KB for the chart. the zoom function was not doing the same transform.

patch zoom issue on avg block size, improve y-axis of price chart on mobile, improve mobile responsiveness of charts

cron only checks empty blocks. Perhaps a completion mechanism for "newly added parsed data" can be added, which would make it easier to add new parsed data in the future. Neon responds very quickly when selecting data ranges in sqp, which is better than a self-hosted database. As for the frontend, an auto-resize function or button can be added to the sidebar, as well as adapting it for mobile devices (with smaller font sizes).

cron only checks empty blocks.

Why ?

imo the indexing function is overengineered already and looking for further optimizations is not the right move (arguably we should take stuff out, but what's in there was only added bc it proved necessary or useful during the initial indexing process).

  • On startup we make sure there are no missed blocks
  • We have daily reconciliations to make sure we have no missed blocks
  • Every time a new block comes in from the ws, we make sure it's the one we expected; if not we fill in missing blocks
  • Every 6 hrs we confirm we are on the chaintip, if not, gap detection, fill us in

It's been empirically tested as this stuff was added following issues experienced with in the initial indexing, including trying to do this all on a free low-memory VPS.

arguably we should get rid of it and make this an easier review. The unique thing I am asking for in this diff review: treat the indexing functionality itself as malleable and an early-stage iteration. This is a bit un-natural, since for chronik itself and for the node software indexing is an incredibly critical function that must be optimized and fault tolerant in all kinds of ways. In this case though, the indexing is not the main point of this app at all. The performance of the indexer is not as important as getting the desired data eventually. We do not expect users or even (most) devs to want to run this, it is designed for devs and hobby analysts.

I plan to add more columns to this database, which will likely drastically overhaul some of the indexing and require its own routines. This type of approach would be stupid if not for the ability to do it with some speed thanks to AI support and the ability to test the indexing functionality itself on individual or batched blocks, which come in strongly typed chronik shapes.

This app is not a production critical indexer. The product is the database itself, and the quality of the database will be confirmed by the quality of the indexing tests. Because chronik blocks and txs are strongly typed, we can have good confidence in the quality of the data. The indexing functionality itself depends a lot on what we want to index -- which we do not exactly know quite yet -- so the indexing functionality is expected to continue changing.

We are optimizing for quantity and flexibility of data, not indexing performance.

On mobile (portrait), the buttons for XEC, BCH, etc are missing.

IMO not important since we mostly care about XEC here anyway but just FYI.

This revision is now accepted and ready to land.Jul 22 2025, 14:19

On mobile (portrait), the buttons for XEC, BCH, etc are missing.

IMO not important since we mostly care about XEC here anyway but just FYI.

could make it more clear -- this area is swipe scrollable on mobile

image.png (1×576 px, 243 KB)

On mobile (portrait), the buttons for XEC, BCH, etc are missing.

IMO not important since we mostly care about XEC here anyway but just FYI.

could make it more clear -- this area is swipe scrollable on mobile

image.png (1×576 px, 243 KB)

In some browsers the scrollbar is obvious at page load but in some it's not.

rebase, add Dockerfiles for CI