Page MenuHomePhabricator

[metachronik, charts.e.cash] Add new indexing to support new charts
ClosedPublic

Authored by bytesofman on Jul 3 2026, 23:58.

Details

Summary

Add address indexing to support new charts with interesting info, like cash fusions and active addresses

Test Plan

npm test

I indexed using this on a separate db and deployed to a vercel preview site. Charts render and can be adjusted for timeframe.

Diff Detail

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

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes

This can't be reviewed. It's 12k lines of new code including tons of AI slop as a doc. It should have remain a draft and be properly split and cleaned for reviewing

This revision now requires changes to proceed.Jul 16 2026, 12:56

imo metachronik should be experimental AI slop. It's not a critical reference and the data is used for charts only. It's more or less a barometer for the current state of LLM dev.

I don't think the data being indexed here is valuable enough to justify a stacked or traditionally reviewable approach.

This is all data that would simply not be indexed at all were it not possible to LLM it and confirm by charts, iterations, and knowing that maintenance and clean up will also be largely left to LLM and probably involve repeated nukes of the whole app.

There's not really a practical way to do this by splitting it up. The indexer either works for the whole blockchain or it doesn't. Adding incremental charts that require a re-index one by one would facilitate review, but it doesn't make practical sense. The time and attention cost of a re-index would mean nothing ever gets added.

Some paths forward.

  1. Using this diff as a basis, do a stacked diff of a greenfield metachronik. We probably get a lot of improvements out of this although it will take some time and the ROI is questionable.
  2. Move it to a public github marked as experimental. We keep charts.e.cash here as the front end, or mb that gets pulled out too.
  3. Leave it in here with some kind of disclaimer. This is easiest for CI and continued improvement, tho yes, it's impossible to review, and the test plan is "can you re-index without hitting snags and produce coherent charts"

Remove review artifacts (ARCHITECTURE-UTXO, debug/monitor/tip scripts, DB copy helpers, dead npm scripts). Align README/env with INITIAL_INDEX_START=0 and TARGET_TX_COUNT_PER_BATCH=30000. Add LLM_REVIEWER_NOTES.md for landing review. Rebase onto current master.

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/cashtab-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build cashtab-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/ecash-herald-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build ecash-herald-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/metachronik-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build metachronik-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/ecash-parse
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build ecash-parse failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/token-server-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build token-server-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/notifications-server-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build notifications-server-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/cashtab-faucet-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build cashtab-faucet-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/mock-chronik-client-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build mock-chronik-client-tests failed with exit code 1

Tail of the build log:

/work /work/abc-ci-builds/b58-ts-tests
Scope: all 25 workspace projects
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build b58-ts-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/chronik-client-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build chronik-client-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/ecash-parse-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build ecash-parse-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/ecash-agora-integration-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build ecash-agora-integration-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/ecash-lib-integration-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build ecash-lib-integration-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/ecash-lib-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build ecash-lib-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/chronik-client-integration-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build chronik-client-integration-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/ecash-agora-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build ecash-agora-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/ecash-wallet-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build ecash-wallet-tests failed with exit code 1

Tail of the build log:

/work /work/abc-ci-builds/ecashaddrjs-tests
Scope: all 25 workspace projects
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build ecashaddrjs-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/ecash-wallet-integration-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build ecash-wallet-integration-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/the-overmind-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build the-overmind-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/marlin-wallet-e2e-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build marlin-wallet-e2e-tests failed with exit code 1

Tail of the build log:

Preparing pnpm@10.24.0 for immediate activation...
/work /work/abc-ci-builds/marlin-wallet-tests
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build marlin-wallet-tests failed with exit code 1

Tail of the build log:

/work /work/abc-ci-builds/cashtab-connect-tests
Scope: all 25 workspace projects
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build cashtab-connect-tests failed with exit code 1

Tail of the build log:

/work /work/abc-ci-builds/ecash-price-tests
Scope: all 25 workspace projects
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with <ROOT>/modules/chronik-client/package.json

Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"

  Failure reason:
  specifiers in the lockfile don't match specifiers in package.json:
* 1 dependencies are mismatched:
  - ws (lockfile: ^8.20.1, manifest: ^8.21.0)

Build ecash-price-tests failed with exit code 1

Refresh pnpm-lock.yaml after rebasing onto current master so frozen pnpm install matches modules/chronik-client ws ^8.21.0.

Fabien requested changes to this revision.Jul 20 2026, 13:04

If it's going by AI, let's review with AI as well

apps/metachronik/LLM_REVIEWER_NOTES.md
1 ↗(On Diff #60366)

This file is useless. If any of this is useful the place is in the diff summary

apps/metachronik/src/services/database.ts
814 ↗(On Diff #60366)

AI: you should consolidate with getHighestBlockHeight and return -1 if empty instead of 0

apps/metachronik/src/services/websocketHandler.ts
173 ↗(On Diff #60366)

AI: This calls processCompletedDay (aggregate + prune) every block, so day_addresses-backed daily metrics are last-block-only and never repaired. Please aggregate without pruning on tip, prune only for completed days, .

web/charts.e.cash/src/app/api/charts/rich-list/route.ts
14 ↗(On Diff #60366)

AI: the parse should be guarded, it can return NaN without throwing

39 ↗(On Diff #60366)

AI: a 400 error code is a better fit

This revision now requires changes to proceed.Jul 20 2026, 13:04

Address Fabien AI review: tip-day aggregate without prune (prune completed days only); consolidate getHighestBlockHeight to return -1 when empty; guard rich-list/token query parses with 400; remove LLM_REVIEWER_NOTES.md (useful bits moved into Summary). Rebased onto current master.

Addressed the AI review inlines:

  • websocketHandler / day finalize: tip day now uses refreshDayAggregation (aggregate only). finalizeCompletedDays prunes completed days only and never prunes the open tip day.
  • getHighestBlockHeight: consolidated with the old getCommittedTipHeight behavior — returns -1 when empty so resume is tip+1 without skipping genesis.
  • rich-list (and token-rich-list / tokens): parse guards; invalid query params return 400.
  • LLM_REVIEWER_NOTES.md: removed; useful landing notes folded into the revision Summary.

Sorry about the accidental earlier "test" conduit comment while wiring the reply API.

Failed tests logs:

====== CashTab Unit Tests: <SendXec /> rendered with params in URL bip21 param - parses op_return_raw for Proof of Writing (POWR) auth/login ======
Error: expect(element).toHaveTextContent()

Expected element to have text content:
  9,513.12 XEC
Received:
  9,513.12
    at toHaveTextContent (/work/cashtab/src/components/Send/__tests__/SendByUrlParams.test.js:605:15)
====== CashTab Unit Tests: <SendXec /> rendered with params in URL bip21 param - parses op_return_raw for eCash Chat Auth ======
Error: expect(element).toHaveTextContent()

Expected element to have text content:
  9,513.12 XEC
Received:
  9,513.12
    at toHaveTextContent (/work/cashtab/src/components/Send/__tests__/SendByUrlParams.test.js:605:15)
    at runNextTicks (node:internal/process/task_queues:65:5)
    at listOnTimeout (node:internal/timers:549:9)
    at processTimers (node:internal/timers:523:7)
====== CashTab Unit Tests: <SendXec /> rendered with params in URL bip21 param - parses op_return_raw for XECX staking reward ======
Error: expect(element).toHaveTextContent()

Expected element to have text content:
  9,513.12 XEC
Received:
  9,513.12
    at toHaveTextContent (/work/cashtab/src/components/Send/__tests__/SendByUrlParams.test.js:605:15)
    at runNextTicks (node:internal/process/task_queues:65:5)
    at listOnTimeout (node:internal/timers:549:9)
    at processTimers (node:internal/timers:523:7)
====== CashTab Unit Tests: <SendXec /> rendered with params in URL bip21 param - parses op_return_raw for Solana Address (SOL0) ======
Error: expect(element).toHaveTextContent()

Expected element to have text content:
  9,513.12 XEC
Received:
  9,513.12
    at toHaveTextContent (/work/cashtab/src/components/Send/__tests__/SendByUrlParams.test.js:605:15)
    at runNextTicks (node:internal/process/task_queues:65:5)
    at listOnTimeout (node:internal/timers:549:9)
    at processTimers (node:internal/timers:523:7)
====== CashTab Unit Tests: <SendXec /> rendered with params in URL bip21 param - parses op_return_raw for DICE bet ======
Error: expect(element).toHaveTextContent()

Expected element to have text content:
  9,513.12 XEC
Received:
  9,513.12
    at toHaveTextContent (/work/cashtab/src/components/Send/__tests__/SendByUrlParams.test.js:605:15)
    at runNextTicks (node:internal/process/task_queues:65:5)
    at listOnTimeout (node:internal/timers:549:9)
    at processTimers (node:internal/timers:523:7)
====== CashTab Unit Tests: <SendXec /> rendered with params in URL bip21 param - parses op_return_raw for ROLL payout ======
Error: expect(element).toHaveTextContent()

Expected element to have text content:
  9,513.12 XEC
Received:
  9,513.12
    at toHaveTextContent (/work/cashtab/src/components/Send/__tests__/SendByUrlParams.test.js:605:15)
    at runNextTicks (node:internal/process/task_queues:65:5)
    at listOnTimeout (node:internal/timers:549:9)
    at processTimers (node:internal/timers:523:7)

Each failure log is accessible here:
CashTab Unit Tests: <SendXec /> rendered with params in URL bip21 param - parses op_return_raw for Proof of Writing (POWR) auth/login
CashTab Unit Tests: <SendXec /> rendered with params in URL bip21 param - parses op_return_raw for eCash Chat Auth
CashTab Unit Tests: <SendXec /> rendered with params in URL bip21 param - parses op_return_raw for XECX staking reward
CashTab Unit Tests: <SendXec /> rendered with params in URL bip21 param - parses op_return_raw for Solana Address (SOL0)
CashTab Unit Tests: <SendXec /> rendered with params in URL bip21 param - parses op_return_raw for DICE bet
CashTab Unit Tests: <SendXec /> rendered with params in URL bip21 param - parses op_return_raw for ROLL payout

cashtab-tests CI needs to be fixed in isolation; issue from header rebase earlier

Rebase onto master (includes Cashtab SendByUrlParams balance assertion fix). Confirmed full cashtab suite passes locally (49 suites / 1179 tests).

Can you please rebase to trigger the ai bot?

apps/metachronik/src/services/database.ts
837 ↗(On Diff #60419)

Rebase onto current master.

bytesofman added inline comments.
apps/metachronik/src/services/database.ts
837 ↗(On Diff #60419)

handled tho not pushed up in latest rebase

Build Bitcoin ABC Diffs / Diff Testing (ai-review) passed.
CodeRabbit Review

Diff : committed changes only
Compare : HEAD → master
Directory : work
────────────────────────────────────────

(\(\
(• .•) Here's looking at you, code.

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/app/api/charts/token-rich-list/route.ts:18web/charts.e.cash/src/app/api/charts/token-rich-list/route.ts:18-22]8;;

Reject partial integer values instead of truncating them.

parseInt accepts malformed limit values such as 10junk and 1.9
rather than returning the documented 400 response. Validate the complete
input and require a safe integer.

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/app/api/charts/tokens/route.ts:17web/charts.e.cash/src/app/api/charts/tokens/route.ts:17-21]8;;

Reject partial integer values instead of truncating them.

parseInt silently accepts malformed values such as limit=10junk and
limit=1.9. Require a complete, safe integer string so invalid requests
reach the existing 400 response.

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/app/api/charts/returning-vs-new-addresses/route.ts:10web/charts.e.cash/src/app/api/charts/returning-vs-new-addresses/route.ts:10-17]8;;

Validate date filters before querying.

start_date and end_date are forwarded without format or range
validation, so malformed values bypass the API’s client-error path. Reject
invalid dates (and an end date preceding the start date) with 400 before
calling the database.

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/app/api/charts/rich-list/route.ts:18web/charts.e.cash/src/app/api/charts/rich-list/route.ts:18-22]8;;

Reject partial integer values instead of truncating them.

parseInt accepts malformed values such as limit=10junk and
limit=1.9, silently treating them as 10 and 1; this conflicts with
the 400 response claiming valid integers are required. Validate the
entire string and require a safe integer.


Proposed fix

-    const parsed = parseInt(value, 10);
-    if (!Number.isFinite(parsed)) {
+    if (!/^[+-]?\d+$/.test(value)) {
         return null;
     }
+    const parsed = Number(value);
+    if (!Number.isSafeInteger(parsed)) {
+        return null;
+    }

────────────────────────────────────────────────────────────────────────

major [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/lib/database.ts:812web/charts.e.cash/src/lib/database.ts:812-841]8;;

Missing UTC date formatting and "incomplete current day" filter —
inconsistent with established convention.

Every pre-existing method querying days/cumulative_X tables
(getDailyStats, getCumulativeClaims, getDailyAgoraVolume,
getCumulativeAgoraVolumeUSD, etc.) formats the date with `to_char(date
AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') as date` and excludes
the current (possibly incomplete) day via `date
♻️ Example fix pattern (apply to each affected method)

             let query = `
-                SELECT date,
+                SELECT to_char(date AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') as date,
                     daily_active_senders,
                     daily_active_addresses
                 FROM days
                 WHERE daily_active_addresses > 0
             `;

             const params: (string | number)[] = [];
             if (startDate && endDate) {
                 query += ' AND date BETWEEN $1 AND $2';
                 params.push(startDate, endDate);
             }
+
+            // Filter out incomplete days (current day)
+            const today = new Date().toISOString().split('T')[0];
+            query += ' AND date < $' + (params.length + 1);
+            params.push(today);

Also applies to: 911-937, 1033-1059, 1061-1087, 1089-1117, 1119-1145,
1147-1181, 1183-1215, 1217-1249

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/lib/database.ts:1147web/charts.e.cash/src/lib/database.ts:1147-1181]8;;

Possible negative returning_addresses with no floor.

daily_active_addresses - new_addresses_count is computed in SQL with no
guard against new_addresses_count exceeding daily_active_addresses. If
that ever happens (e.g., data drift), the chart would show a negative bar
instead of a clamped 0.






🛡️ Proposed fix

-                    daily_active_addresses - new_addresses_count as returning_addresses,
+                    GREATEST(daily_active_addresses - new_addresses_count, 0) as returning_addresses,

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/config/chartOptions.ts:355web/charts.e.cash/src/config/chartOptions.ts:355-364]8;;

returning-vs-new-addresses renders as stacked bars but lacks
sumFields.

In ChartRenderer, this chart stacks returning_addresses and
new_addresses (stackId="a"), so the visible max per day is their sum.
Without sumFields: true, getDataMax in page.tsx uses only
fields[0] (returning_addresses), underestimating the auto-zoom
baseline.


Proposed fix

         dataConfig: {
             dataKey: 'completeReturningVsNewAddresses',
             fields: ['returning_addresses', 'new_addresses'],
+            sumFields: true,
         },

────────────────────────────────────────────────────────────────────────

minor [Maintainability & Code Quality]
→ ]8;;vscode://file//work/apps/metachronik/src/services/knownDuplicateCoinbases.ts:38apps/metachronik/src/services/knownDuplicateCoinbases.ts:38-41]8;;

Doc comment height is wrong (91712 vs computed 91722).

KNOWN_DUPLICATE_COINBASE_FIRST_HEIGHT evaluates to `Math.min(91722,
91880, 91812, 91842) === 91722`, but the comment states the first height
is 91712. The constant is correct; only the comment is off by 10, which
is misleading for anyone using it to reason about the guard boundary.





✏️ Comment fix

-/** First height where a known duplicate coinbase appears (91712). */
+/** First height where a known duplicate coinbase appears (91722). */

────────────────────────────────────────────────────────────────────────

critical [Data Integrity & Integration]
→ ]8;;vscode://file//work/apps/metachronik/src/services/database.ts:998apps/metachronik/src/services/database.ts:998-1134]8;;

Critical: migrateSchema() never adds the new blocks/days columns, so
upgrades break.

This method is documented as bringing an existing DB up to schema.sql
shape, and initializeTables() runs it before executing schema.sql. But
it only alters addresses and creates the UTXO/token tables — it does not
add the new columns to existing blocks (unique_senders,
fusion_tx_count, agora_unique_traders, lokad_tx_count) or days
(unique_senders … new_addresses_count, new_miners_count,
new_stakers_count, etc.).

On an existing database:
- CREATE TABLE IF NOT EXISTS days/blocks in schema.sql is a no-op, so
those columns are never added.
- schema.sql then fails creating cumulative_addresses (references
new_addresses_count) and cumulative_miners_stakers (references
new_miners_count/new_stakers_count).
- saveBlocks and aggregateDailyData inserts reference the missing
columns and error out.

Add guarded ALTER TABLE ... ADD COLUMN IF NOT EXISTS for every new
blocks/days column.





🛠️ Proposed migration additions

DO $$
BEGIN
    IF to_regclass('public.blocks') IS NOT NULL THEN
        ALTER TABLE blocks
            ADD COLUMN IF NOT EXISTS unique_senders INTEGER NOT NULL DEFAULT 0,
            ADD COLUMN IF NOT EXISTS fusion_tx_count INTEGER NOT NULL DEFAULT 0,
            ADD COLUMN IF NOT EXISTS agora_unique_traders INTEGER NOT NULL DEFAULT 0,
            ADD COLUMN IF NOT EXISTS lokad_tx_count INTEGER NOT NULL DEFAULT 0;
    END IF;
    IF to_regclass('public.days') IS NOT NULL THEN
        ALTER TABLE days
            ADD COLUMN IF NOT EXISTS unique_senders INTEGER NOT NULL DEFAULT 0,
            ADD COLUMN IF NOT EXISTS fusion_tx_count INTEGER NOT NULL DEFAULT 0,
            ADD COLUMN IF NOT EXISTS agora_unique_traders INTEGER NOT NULL DEFAULT 0,
            ADD COLUMN IF NOT EXISTS lokad_tx_count INTEGER NOT NULL DEFAULT 0,
            ADD COLUMN IF NOT EXISTS daily_active_senders INTEGER NOT NULL DEFAULT 0,
            ADD COLUMN IF NOT EXISTS daily_active_addresses INTEGER NOT NULL DEFAULT 0,
            ADD COLUMN IF NOT EXISTS daily_agora_unique_traders INTEGER NOT NULL DEFAULT 0,
            ADD COLUMN IF NOT EXISTS daily_unique_miners INTEGER NOT NULL DEFAULT 0,
            ADD COLUMN IF NOT EXISTS daily_unique_stakers INTEGER NOT NULL DEFAULT 0,
            ADD COLUMN IF NOT EXISTS new_miners_count INTEGER NOT NULL DEFAULT 0,
            ADD COLUMN IF NOT EXISTS new_stakers_count INTEGER NOT NULL DEFAULT 0,
            ADD COLUMN IF NOT EXISTS daily_coinbase_recipients INTEGER NOT NULL DEFAULT 0,
            ADD COLUMN IF NOT EXISTS new_addresses_count INTEGER NOT NULL DEFAULT 0;
    END IF;
END $$;

Run this inside migrateSchema() (before schema.sql executes). Note the
generated days columns already exist in schema.sql; verify column set
against the final schema.

────────────────────────────────────────────────────────────────────────

minor [Maintainability & Code Quality]
→ ]8;;vscode://file//work/apps/metachronik/src/scripts/checkIndexing.ts:361apps/metachronik/src/scripts/checkIndexing.ts:361-362]8;;

Supply units in the message disagree with the constant.

MAX_SUPPLY_SATS encodes 21 trillion XEC, but this warning prints `~21B
XEC. Update the string to ~21T XEC` to avoid confusing operators.

────────────────────────────────────────────────────────────────────────

major [Data Integrity & Integration]
→ ]8;;vscode://file//work/apps/metachronik/src/services/tokenBlockDeltas.ts:66apps/metachronik/src/services/tokenBlockDeltas.ts:66-69]8;;

Avoid double-counting burn atoms. actualBurnAtoms and
intentionalBurnAtoms are separate burn measures, not additive; summing
them inflates b.burnAtoms for any intentional burn. Use
actualBurnAtoms alone here.

────────────────────────────────────────────────────────────────────────

major [Functional Correctness]
→ ]8;;vscode://file//work/apps/metachronik/src/scripts/checkIndexing.ts:582apps/metachronik/src/scripts/checkIndexing.ts:582-604]8;;

Type mismatch breaks the holder drift query

balance_atoms is cast to text while utxo_sum is bigint, but the
outer query compares and subtracts them (!= and -). Postgres has no
text bigint or text - bigint operator, so this query will fail at
runtime. Cast balance_atoms to bigint here.

────────────────────────────────────────
Review complete
12 findings ✔

Critical 1
Major 3
Minor 8

54 files reviewed:

  • apps/metachronik/PERFORMANCE_OPTIMIZATION.md
  • apps/metachronik/README.md
  • apps/metachronik/env.example
  • apps/metachronik/package.json
  • apps/metachronik/scripts/README.md
  • apps/metachronik/src/database/connection.ts
  • apps/metachronik/src/database/schema.sql
  • apps/metachronik/src/index.ts
  • apps/metachronik/src/scripts/checkIndexing.ts
  • apps/metachronik/src/scripts/repairEmptyScriptUtxos.ts

... and 44 more files
────────────────────────────────────────

Print all AI prompts: coderabbit review --show-prompts

bytesofman marked an inline comment as done.

Address CodeRabbit review (except burn double-count pending confirmation): migrateSchema ADD COLUMN for new blocks/days fields; charts UTC date formatting + incomplete-day filter; strict integer/date query validation; returning-vs-new sumFields + GREATEST floor; checkIndexing numeric casts + 21T wording; duplicate-coinbase comment height.

The build failed due to an unexpected infrastructure outage. The administrators have been notified to investigate. Sorry for the inconvenience.

Build Bitcoin ABC Diffs / Diff Testing (ai-review) passed.
CodeRabbit Review

Diff : committed changes only
Compare : HEAD → master
Directory : work
────────────────────────────────────────

(\(\
(• .•) Thread behaviour? I don't even know her.

────────────────────────────────────────────────────────────────────────

major [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/lib/database.ts:1371web/charts.e.cash/src/lib/database.ts:1371-1394]8;;

Make includeMintBatons include zero-atom batons.

Lines 1383-1385 still require atoms >= 1 by default, so zero-atom mint
baton rows are excluded even when includeMintBatons is true.


Proposed fix

                 FROM token_balances
                 WHERE token_id = $1
-                  AND atoms >= $2
+                  AND (
+                      atoms >= $2
+                      OR ($3::boolean AND is_mint_baton = TRUE)
+                  )
                   AND ($3::boolean OR is_mint_baton = FALSE)

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/lib/chartQueryParams.ts:28web/charts.e.cash/src/lib/chartQueryParams.ts:28-64]8;;

Reject impossible calendar dates.

Line 52 accepts values such as 2025-02-30; they reach the database date
filter and can produce a server error instead of the documented validation
failure.


Proposed fix

 const ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
 
+function isValidIsoDate(value: string): boolean {
+    return (
+        ISO_DATE_RE.test(value) &&
+        new Date(`${value}T00:00:00.000Z`).toISOString().slice(0, 10) ===
+            value
+    );
+}
+
 ...
-    if (!ISO_DATE_RE.test(startDate!) || !ISO_DATE_RE.test(endDate!)) {
+    if (!isValidIsoDate(startDate!) || !isValidIsoDate(endDate!)) {

────────────────────────────────────────────────────────────────────────

major [Stability & Availability]
→ ]8;;vscode://file//work/apps/metachronik/package.json:9apps/metachronik/package.json:9-11]8;;

Do not use an 8192 MB heap cap on the documented 8 GB host.

This leaves no memory budget for native allocations, PostgreSQL buffers,
and the operating system. Make the heap limit deployment-configurable, or
default to approximately 4096 MB for the documented 8 GB plan and reserve
8192 MB for larger hosts.

────────────────────────────────────────────────────────────────────────

major [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/components/ChartRenderer.tsx:113web/charts.e.cash/src/components/ChartRenderer.tsx:113-156]8;;

Inline the fork reference lines
ReferenceLine must be a direct chart child in Recharts; wrapping it in
ForkReferenceLines can prevent the BCH/XEC markers from rendering across
the chart variants.

────────────────────────────────────────────────────────────────────────

minor [Stability & Availability]
→ ]8;;vscode://file//work/apps/metachronik/src/scripts/repairEmptyScriptUtxos.ts:104apps/metachronik/src/scripts/repairEmptyScriptUtxos.ts:104-121]8;;

Guard against non-positive --batch-size.

parseArg accepts any finite number, so --batch-size 0 (or a negative
value) makes start += batchSize never advance, producing an infinite
scan loop. Clamp to a sane minimum.






🛡️ Proposed guard

-        const batchSize = parseArg('--batch-size') ?? 100;
+        const batchSizeArg = parseArg('--batch-size') ?? 100;
+        const batchSize = Math.max(1, Math.floor(batchSizeArg));

────────────────────────────────────────────────────────────────────────

minor [Stability & Availability]
→ ]8;;vscode://file//work/apps/metachronik/src/database/connection.ts:62apps/metachronik/src/database/connection.ts:62-64]8;;

Attach a .catch to the fire-and-forget SET statement_timeout.

void client.query(...) discards the return value but the promise still
rejects if the SET fails (e.g. transient error on a freshly connected
client), producing an unhandled promise rejection that can crash the
process.


🛡️ Proposed fix

         this.pool.on('connect', (client: PoolClient) => {
-            void client.query(`SET statement_timeout = ${statementTimeoutMs}`);
+            client
+                .query(`SET statement_timeout = ${statementTimeoutMs}`)
+                .catch(err =>
+                    logger.warn('Failed to set statement_timeout:', err),
+                );
         });

────────────────────────────────────────────────────────────────────────

minor [Stability & Availability]
→ ]8;;vscode://file//work/apps/metachronik/src/database/connection.ts:30apps/metachronik/src/database/connection.ts:30-36]8;;

Guard against a non-numeric STATEMENT_TIMEOUT_MS.

parseInt returns NaN for a malformed env value (e.g. "5m"), and the
|| fallback won't catch it since NaN is only produced after parsing.
The resulting SET statement_timeout = NaN then fails on every new pooled
connection.


🛡️ Proposed fix

-        this.defaultStatementTimeoutMs = parseInt(
-            process.env.STATEMENT_TIMEOUT_MS ||
-                String(DEFAULT_STATEMENT_TIMEOUT_MS),
-            10,
-        );
+        const parsedTimeout = parseInt(
+            process.env.STATEMENT_TIMEOUT_MS ||
+                String(DEFAULT_STATEMENT_TIMEOUT_MS),
+            10,
+        );
+        this.defaultStatementTimeoutMs = Number.isFinite(parsedTimeout)
+            ? parsedTimeout
+            : DEFAULT_STATEMENT_TIMEOUT_MS;

────────────────────────────────────────────────────────────────────────

minor [Maintainability & Code Quality]
→ ]8;;vscode://file//work/apps/metachronik/scripts/README.md:155apps/metachronik/scripts/README.md:155-157]8;;

Broken sentence / stray bullet.

"Deploy schema" is split from "code and restart" by a blank line, turning
the continuation into an unintended list item and reading as an incomplete
sentence. Likely intended as a single line.






📝 Suggested wording

-Token tables are empty until the first ALP/SLP tx (~block 500k). Deploy schema
-
-- code and restart **without** `--reindex`.
+Token tables are empty until the first ALP/SLP tx (~block 500k). Deploy schema +
+code and restart **without** `--reindex`.

────────────────────────────────────────────────────────────────────────

minor [Data Integrity & Integration]
→ ]8;;vscode://file//work/apps/metachronik/src/services/tokenBlockDeltas.ts:66apps/metachronik/src/services/tokenBlockDeltas.ts:66-69]8;;

Avoid double-counting burn atoms. actualBurnAtoms already covers the
burned total, so adding intentionalBurnAtoms inflates burnAtoms. Use
actualBurnAtoms here.

────────────────────────────────────────
Review complete
9 findings ✔

Major 3
Minor 6

55 files reviewed:

  • apps/metachronik/PERFORMANCE_OPTIMIZATION.md
  • apps/metachronik/README.md
  • apps/metachronik/env.example
  • apps/metachronik/package.json
  • apps/metachronik/scripts/README.md
  • apps/metachronik/src/database/connection.ts
  • apps/metachronik/src/database/schema.sql
  • apps/metachronik/src/index.ts
  • apps/metachronik/src/scripts/checkIndexing.ts
  • apps/metachronik/src/scripts/repairEmptyScriptUtxos.ts

... and 45 more files
────────────────────────────────────────

Print all AI prompts: coderabbit review --show-prompts

CodeRabbit follow-ups: validate real calendar dates; clamp repair --batch-size; guard STATEMENT_TIMEOUT_MS NaN + catch SET failures; fix scripts README; document that mint batons are 0-atom (default rich-list min_atoms excludes them). Skip ForkReferenceLines (recharts 3 + verified on charts) and burn double-count pending decision.

Fix token block burn deltas: count actualBurnAtoms only (do not add intentionalBurnAtoms). Historical block_token_deltas burns stay inflated until a reindex; not charted today.

The build failed due to an unexpected infrastructure outage. The administrators have been notified to investigate. Sorry for the inconvenience.

Tail of the build log:

 WARN  GET https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/debug/-/debug-4.4.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/ms/-/ms-2.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/json5/-/json5-2.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/commander/-/commander-6.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
Progress: resolved 1014, reused 0, downloaded 992, added 992
Progress: resolved 1014, reused 0, downloaded 995, added 996
Progress: resolved 1014, reused 0, downloaded 996, added 996
Progress: resolved 1014, reused 0, downloaded 999, added 1000
 WARN  GET https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/debug/-/debug-4.4.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/ms/-/ms-2.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/json5/-/json5-2.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/commander/-/commander-6.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
Progress: resolved 1014, reused 0, downloaded 1000, added 1000
Progress: resolved 1014, reused 0, downloaded 1000, added 1001
Progress: resolved 1014, reused 0, downloaded 1001, added 1001
Progress: resolved 1014, reused 0, downloaded 1001, added 1002
Progress: resolved 1014, reused 0, downloaded 1002, added 1002
Progress: resolved 1014, reused 0, downloaded 1003, added 1005
Progress: resolved 1014, reused 0, downloaded 1004, added 1005
Progress: resolved 1014, reused 0, downloaded 1005, added 1007
Progress: resolved 1014, reused 0, downloaded 1006, added 1007
Progress: resolved 1014, reused 0, downloaded 1007, added 1009
Progress: resolved 1014, reused 0, downloaded 1008, added 1009
Progress: resolved 1014, reused 0, downloaded 1009, added 1011
Progress: resolved 1014, reused 0, downloaded 1010, added 1011
Progress: resolved 1014, reused 0, downloaded 1011, added 1013
 ERR_SOCKET_TIMEOUT  request to https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz failed, reason: Socket timeout

FetchError: request to https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz failed, reason: Socket timeout
    at ClientRequest.<anonymous> (/root/.cache/node/corepack/v1/pnpm/10.24.0/dist/pnpm.cjs:41976:18)
    at ClientRequest.emit (node:events:519:28)
    at emitErrorEvent (node:_http_client:107:11)
    at TLSSocket.socketErrorListener (node:_http_client:574:5)
    at TLSSocket.emit (node:events:531:35)
    at emitErrorNT (node:internal/streams/destroy:170:8)
    at emitErrorCloseNT (node:internal/streams/destroy:129:3)
    at processTicksAndRejections (node:internal/process/task_queues:90:21)
    at runNextTicks (node:internal/process/task_queues:69:3)
    at listOnTimeout (node:internal/timers:549:9)
Build ecash-wallet-tests failed with exit code 1

Tail of the build log:

 WARN  GET https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001787.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.335.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/semver/-/semver-6.3.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/debug/-/debug-4.4.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/ms/-/ms-2.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/json5/-/json5-2.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/commander/-/commander-6.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/cli/-/cli-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001787.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.335.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/semver/-/semver-6.3.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/debug/-/debug-4.4.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/ms/-/ms-2.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/json5/-/json5-2.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/commander/-/commander-6.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 ERR_SOCKET_TIMEOUT  request to https://registry.npmjs.org/@babel/cli/-/cli-7.28.6.tgz failed, reason: Socket timeout

FetchError: request to https://registry.npmjs.org/@babel/cli/-/cli-7.28.6.tgz failed, reason: Socket timeout
    at ClientRequest.<anonymous> (/root/.cache/node/corepack/v1/pnpm/10.24.0/dist/pnpm.cjs:41976:18)
    at ClientRequest.emit (node:events:519:28)
    at emitErrorEvent (node:_http_client:107:11)
    at TLSSocket.socketErrorListener (node:_http_client:574:5)
    at TLSSocket.emit (node:events:531:35)
    at emitErrorNT (node:internal/streams/destroy:170:8)
    at emitErrorCloseNT (node:internal/streams/destroy:129:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:90:21)
Build ecash-wallet-integration-tests failed with exit code 1

Tail of the build log:

 WARN  GET https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
Progress: resolved 2665, reused 0, downloaded 2532, added 2646
Progress: resolved 2665, reused 0, downloaded 2532, added 2647
Progress: resolved 2665, reused 0, downloaded 2533, added 2647
Progress: resolved 2665, reused 0, downloaded 2533, added 2648
Progress: resolved 2665, reused 0, downloaded 2534, added 2648
Progress: resolved 2665, reused 0, downloaded 2534, added 2649
Progress: resolved 2665, reused 0, downloaded 2535, added 2650
Progress: resolved 2665, reused 0, downloaded 2536, added 2650
Progress: resolved 2665, reused 0, downloaded 2536, added 2651
Progress: resolved 2665, reused 0, downloaded 2537, added 2651
Progress: resolved 2665, reused 0, downloaded 2537, added 2652
Progress: resolved 2665, reused 0, downloaded 2538, added 2653
Progress: resolved 2665, reused 0, downloaded 2539, added 2653
Progress: resolved 2665, reused 0, downloaded 2539, added 2654
Progress: resolved 2665, reused 0, downloaded 2540, added 2654
Progress: resolved 2665, reused 0, downloaded 2541, added 2656
Progress: resolved 2665, reused 0, downloaded 2542, added 2656
Progress: resolved 2665, reused 0, downloaded 2542, added 2657
Progress: resolved 2665, reused 0, downloaded 2543, added 2657
Progress: resolved 2665, reused 0, downloaded 2543, added 2658
 ERR_SOCKET_TIMEOUT  request to https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz failed, reason: Socket timeout

FetchError: request to https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz failed, reason: Socket timeout
    at ClientRequest.<anonymous> (/root/.cache/node/corepack/v1/pnpm/10.24.0/dist/pnpm.cjs:41976:18)
    at ClientRequest.emit (node:events:519:28)
    at emitErrorEvent (node:_http_client:107:11)
    at TLSSocket.socketErrorListener (node:_http_client:574:5)
    at TLSSocket.emit (node:events:531:35)
    at emitErrorNT (node:internal/streams/destroy:170:8)
    at emitErrorCloseNT (node:internal/streams/destroy:129:3)
    at processTicksAndRejections (node:internal/process/task_queues:90:21)
    at runNextTicks (node:internal/process/task_queues:69:3)
    at listOnTimeout (node:internal/timers:549:9)
Build ecash-price-tests failed with exit code 1

Tail of the build log:

 WARN  GET https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001787.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.335.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/semver/-/semver-6.3.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/debug/-/debug-4.4.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/ms/-/ms-2.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/json5/-/json5-2.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/commander/-/commander-6.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/cli/-/cli-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001787.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.335.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/semver/-/semver-6.3.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/debug/-/debug-4.4.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/ms/-/ms-2.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/json5/-/json5-2.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/commander/-/commander-6.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 ERR_SOCKET_TIMEOUT  request to https://registry.npmjs.org/@babel/cli/-/cli-7.28.6.tgz failed, reason: Socket timeout

FetchError: request to https://registry.npmjs.org/@babel/cli/-/cli-7.28.6.tgz failed, reason: Socket timeout
    at ClientRequest.<anonymous> (/root/.cache/node/corepack/v1/pnpm/10.24.0/dist/pnpm.cjs:41976:18)
    at ClientRequest.emit (node:events:519:28)
    at emitErrorEvent (node:_http_client:107:11)
    at TLSSocket.socketErrorListener (node:_http_client:574:5)
    at TLSSocket.emit (node:events:531:35)
    at emitErrorNT (node:internal/streams/destroy:170:8)
    at emitErrorCloseNT (node:internal/streams/destroy:129:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:90:21)
Build marlin-wallet-tests failed with exit code 1
The build failed due to an unexpected infrastructure outage. The administrators have been notified to investigate. Sorry for the inconvenience.

Tail of the build log:

 WARN  GET https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
Progress: resolved 661, reused 0, downloaded 641, added 643
Progress: resolved 661, reused 0, downloaded 642, added 643
Progress: resolved 661, reused 0, downloaded 642, added 644
Progress: resolved 661, reused 0, downloaded 643, added 644
 WARN  GET https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
Progress: resolved 661, reused 0, downloaded 644, added 646
Progress: resolved 661, reused 0, downloaded 645, added 646
Progress: resolved 661, reused 0, downloaded 645, added 647
Progress: resolved 661, reused 0, downloaded 646, added 647
Progress: resolved 661, reused 0, downloaded 648, added 650
Progress: resolved 661, reused 0, downloaded 649, added 650
Progress: resolved 661, reused 0, downloaded 650, added 652
Progress: resolved 661, reused 0, downloaded 651, added 652
Progress: resolved 661, reused 0, downloaded 651, added 653
Progress: resolved 661, reused 0, downloaded 652, added 653
Progress: resolved 661, reused 0, downloaded 652, added 654
Progress: resolved 661, reused 0, downloaded 653, added 654
Progress: resolved 661, reused 0, downloaded 653, added 655
Progress: resolved 661, reused 0, downloaded 654, added 655
Progress: resolved 661, reused 0, downloaded 654, added 656
 ERR_SOCKET_TIMEOUT  request to https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz failed, reason: Socket timeout

FetchError: request to https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz failed, reason: Socket timeout
    at ClientRequest.<anonymous> (/root/.cache/node/corepack/v1/pnpm/10.24.0/dist/pnpm.cjs:41976:18)
    at ClientRequest.emit (node:events:519:28)
    at emitErrorEvent (node:_http_client:107:11)
    at TLSSocket.socketErrorListener (node:_http_client:574:5)
    at TLSSocket.emit (node:events:531:35)
    at emitErrorNT (node:internal/streams/destroy:170:8)
    at emitErrorCloseNT (node:internal/streams/destroy:129:3)
    at processTicksAndRejections (node:internal/process/task_queues:90:21)
    at runNextTicks (node:internal/process/task_queues:69:3)
    at listOnTimeout (node:internal/timers:549:9)
Build cashtab-tests failed with exit code 1

Tail of the build log:

 WARN  GET https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/cors/-/cors-2.8.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/express/-/express-5.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/wif/-/wif-2.0.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/cors/-/cors-2.8.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/express/-/express-5.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
Progress: resolved 1603, reused 97, downloaded 1469, added 1581
Progress: resolved 1603, reused 97, downloaded 1470, added 1583
Progress: resolved 1603, reused 97, downloaded 1471, added 1583
Progress: resolved 1603, reused 97, downloaded 1471, added 1584
Progress: resolved 1603, reused 97, downloaded 1472, added 1584
Progress: resolved 1603, reused 97, downloaded 1472, added 1585
Progress: resolved 1603, reused 97, downloaded 1473, added 1585
Progress: resolved 1603, reused 97, downloaded 1474, added 1587
Progress: resolved 1603, reused 97, downloaded 1475, added 1587
Progress: resolved 1603, reused 97, downloaded 1476, added 1589
Progress: resolved 1603, reused 97, downloaded 1477, added 1589
Progress: resolved 1603, reused 97, downloaded 1477, added 1590
Progress: resolved 1603, reused 97, downloaded 1478, added 1591
Progress: resolved 1603, reused 97, downloaded 1479, added 1591
Progress: resolved 1603, reused 97, downloaded 1481, added 1594
Progress: resolved 1603, reused 97, downloaded 1482, added 1594
 ERR_SOCKET_TIMEOUT  request to https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz failed, reason: Socket timeout

FetchError: request to https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz failed, reason: Socket timeout
    at ClientRequest.<anonymous> (/root/.cache/node/corepack/v1/pnpm/10.24.0/dist/pnpm.cjs:41976:18)
    at ClientRequest.emit (node:events:519:28)
    at emitErrorEvent (node:_http_client:107:11)
    at TLSSocket.socketErrorListener (node:_http_client:574:5)
    at TLSSocket.emit (node:events:531:35)
    at emitErrorNT (node:internal/streams/destroy:170:8)
    at emitErrorCloseNT (node:internal/streams/destroy:129:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:90:21)
Build ecash-lib-integration-tests failed with exit code 1

Build Bitcoin ABC Diffs / Diff Testing (ai-review) passed.
CodeRabbit Review

Diff : committed changes only
Compare : HEAD → master
Directory : work
────────────────────────────────────────

(\(\
(• .•) Weeks of programming can save you hours of planning.

────────────────────────────────────────────────────────────────────────

major [Stability & Availability]
→ ]8;;vscode://file//work/apps/metachronik/src/database/schema.sql:118apps/metachronik/src/database/schema.sql:118-122]8;;

Use INTEGER for both vout columns.

Lines 118 and 147 limit output indexes to 32,767. Transaction outpoints
use unsigned 32-bit indexes, so a valid high-index output will fail
persistence and halt indexing. (documentation.cash)


Proposed fix

-    vout SMALLINT NOT NULL,
+    vout INTEGER NOT NULL,
...
-    vout SMALLINT NOT NULL,
+    vout INTEGER NOT NULL,

Also applies to: 146-155

────────────────────────────────────────────────────────────────────────

minor [Stability & Availability]
→ ]8;;vscode://file//work/apps/metachronik/env.example:27apps/metachronik/env.example:27-32]8;;

Scope or lower the default batch target.

30000 is the upper edge of the documented range for ~8GB hosts, and the
performance guide reports occasional crashes even with the recommended
settings. Either use a conservative default such as 25000, or state
explicitly that this template assumes an ~8GB host and requires tuning.

────────────────────────────────────────────────────────────────────────

major [Data Integrity & Integration]
→ ]8;;vscode://file//work/apps/metachronik/src/services/tokenBlockDeltas.ts:66apps/metachronik/src/services/tokenBlockDeltas.ts:66-74]8;;

Avoid double-counting intentional burns. actualBurnAtoms already covers
the total burned amount, so adding intentionalBurnAtoms here inflates
persisted supply deltas. Use actual alone.

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/app/api/charts/token-rich-list/route.ts:29web/charts.e.cash/src/app/api/charts/token-rich-list/route.ts:29-50]8;;

Allow min_atoms=0 as documented.

Line 38 rewrites min_atoms=0 to 1, so callers cannot retrieve
zero-atom mint batons despite the contract in Lines 46-48.


Proposed fix

             }
             const parsedMinAtoms = BigInt(minAtomsRaw || '1');
-            minAtoms = parsedMinAtoms < BigInt(1) ? BigInt(1) : parsedMinAtoms;
+            if (parsedMinAtoms < BigInt(0)) {
+                throw new Error('invalid');
+            }
+            minAtoms = parsedMinAtoms;

────────────────────────────────────────────────────────────────────────

major [Stability & Availability]
→ ]8;;vscode://file//work/apps/metachronik/src/database/connection.ts:26apps/metachronik/src/database/connection.ts:26-27]8;;

Track every in-flight client before shutdown.

activeClient is overwritten by concurrent queries, and
transactionWithStatementTimeout is not tracked at all. Consequently,
close() may cancel only one statement and then wait for other
long-running operations during pool.end().

Track query and transaction clients in a Set, then cancel a snapshot
during shutdown.




Also applies to: 93-118, 215-244

────────────────────────────────────────────────────────────────────────

major [Data Integrity & Integration]
→ ]8;;vscode://file//work/apps/metachronik/src/services/database.ts:41apps/metachronik/src/services/database.ts:41-53]8;;

Separate persisted block rows from event-bearing blocks.

Block now requires script and event arrays that are never persisted,
while getBlocksInRange() returns database rows typed as Block[].
Callers can therefore access properties such as utxo_events that are
actually undefined.

Use separate types for processed block input and persisted block metrics.




Also applies to: 940-949

────────────────────────────────────────────────────────────────────────

major [Data Integrity & Integration]
→ ]8;;vscode://file//work/apps/metachronik/src/services/database.ts:543apps/metachronik/src/services/database.ts:543-553]8;;

Track the first miner/staker date separately.

first_seen records when an address first appeared, not when it first
mined or staked. A previously known address entering either role is
excluded from that day and may be attributed retroactively to its original
address date.

Persist first_miner_seen and first_staker_seen, setting each on its
first corresponding event.




Also applies to: 787-794

────────────────────────────────────────────────────────────────────────

major [Data Integrity & Integration]
→ ]8;;vscode://file//work/apps/metachronik/src/services/database.ts:228apps/metachronik/src/services/database.ts:228-264]8;;

Do not use MAX(days.date) as the finalized-day watermark.

When includeTipDay refreshes tip day D, it inserts D into days
without pruning. After the chain advances to D+1, MAX(date) is already
D, so the date > latestMerged filter permanently skips finalizing D.
Its aggregate may remain stale and its day_addresses rows are never
pruned.

Persist a distinct finalized watermark/status instead of inferring
finalization from row existence.

────────────────────────────────────────────────────────────────────────

major [Data Integrity & Integration]
→ ]8;;vscode://file//work/apps/metachronik/src/services/utxoApply.ts:182apps/metachronik/src/services/utxoApply.ts:182-203]8;;

Persist first-seen addresses even when their batch delta is zero.

A script created and spent within the same batch is skipped here, so no
addresses row or first_seen date is recorded. This undercounts
cumulative and new-address analytics.




Proposed fix

         for (const [script, delta] of state.balanceDelta) {
-            if (delta === 0n) {
-                continue;
-            }
             scripts.push(script);
             dates.push(state.firstSeenDate.get(script) ?? '');
             deltas.push(delta);

────────────────────────────────────────────────────────────────────────

major [Data Integrity & Integration]
→ ]8;;vscode://file//work/apps/metachronik/src/services/tokenApply.ts:242apps/metachronik/src/services/tokenApply.ts:242-290]8;;

Insert metadata for every seen token, not only surviving UTXOs.

If all outputs for a newly encountered token are spent within this batch,
it disappears from state.pending and is never inserted into tokens.
Iterate state.seenTokens independently of the UTXO insertion branch.




Proposed fix

-        const tokenIds: string[] = [];
-        const protocols: string[] = [];
-        const types: string[] = [];
-        const heights: number[] = [];
-        const emitted = new Set<string>();
-        for (const utxo of state.pending.values()) {
-            if (emitted.has(utxo.tokenId)) {
-                continue;
-            }
-            emitted.add(utxo.tokenId);
-            const meta = state.seenTokens.get(utxo.tokenId);
-            tokenIds.push(utxo.tokenId);
-            protocols.push(meta?.tokenProtocol ?? utxo.tokenProtocol);
-            types.push(meta?.tokenType ?? utxo.tokenType);
-            heights.push(meta?.firstSeenHeight ?? utxo.createdHeight);
-        }
+    }
+
+    if (state.seenTokens.size > 0) {
+        const tokenIds: string[] = [];
+        const protocols: string[] = [];
+        const types: string[] = [];
+        const heights: number[] = [];
+
+        for (const [tokenId, meta] of state.seenTokens) {
+            tokenIds.push(tokenId);
+            protocols.push(meta.tokenProtocol);
+            types.push(meta.tokenType);
+            heights.push(meta.firstSeenHeight);
+        }
+
         if (tokenIds.length > 0) {
             await client.query(
                 `INSERT INTO tokens (token_id, token_protocol, token_type, first_seen_height)

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/components/ChartRenderer.tsx:348web/charts.e.cash/src/components/ChartRenderer.tsx:348-352]8;;

Expose the loading status to assistive technology.

The spinner and message have no live-region semantics, so screen-reader
users are not notified when chart data starts loading.






Proposed fix

-        <div className="absolute inset-0 z-30 flex flex-col items-center justify-center bg-[#090916]/75">
-            <div className="h-16 w-16 animate-spin rounded-full border-b-2 border-[#01a0e0]" />
+        <div
+            role="status"
+            aria-live="polite"
+            className="absolute inset-0 z-30 flex flex-col items-center justify-center bg-[#090916]/75"
+        >
+            <div
+                aria-hidden="true"
+                className="h-16 w-16 animate-spin rounded-full border-b-2 border-[#01a0e0]"
+            />

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/components/ChartRenderer.tsx:3012web/charts.e.cash/src/components/ChartRenderer.tsx:3012-3018]8;;

Do not show the reindex warning while data is loading.

On the initial request, entries is empty while isLoading is true, so
the translucent overlay displays over a misleading failure message.






Proposed fix

-                {entries.length === 0 ? (
+                {!isLoading && entries.length === 0 ? (
                     <div className="flex h-64 items-center justify-center text-gray-400">
                         <p>
                             No balance data yet. Run a full reindex to populate
                             the rich list.
                         </p>
                     </div>
-                ) : (
+                ) : entries.length > 0 ? (
                     <div className="max-h-[600px] overflow-auto rounded-lg border border-gray-800">

-                    </div>
-                )}
+                    </div>
+                ) : null}

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/config/chartOptions.ts:255web/charts.e.cash/src/config/chartOptions.ts:255-263]8;;

Zoom Y-max likely understated for daily-active-addresses.

fields: ['daily_active_senders', 'daily_active_addresses'] has no
sumFields: true, so getDataMax in page.tsx uses only fields[0]
('daily_active_senders') when computing the zoom max. Since
"daily_active_addresses" ("sent or received") is a superset of senders
alone, it will typically be ≥ daily_active_senders, so the initial
zoom-in max/min bound is calculated from the smaller series — the larger
daily_active_addresses line can get clipped once the user starts
zooming.






🐛 Proposed fix — put the larger series first

     {
         id: 'daily-active-addresses',
         name: 'Daily Active Addresses',
         description: 'True unique addresses active per day (sent or received)',
         dataConfig: {
             dataKey: 'completeDailyActiveAddresses',
-            fields: ['daily_active_senders', 'daily_active_addresses'],
+            fields: ['daily_active_addresses', 'daily_active_senders'],
         },
     },

────────────────────────────────────────────────────────────────────────

major [Data Integrity & Integration]
→ ]8;;vscode://file//work/apps/metachronik/src/index.ts:414apps/metachronik/src/index.ts:414-419]8;;

Preserve the active tip day's staging data.

These calls use includeTipDay: true, while the WebSocket path explicitly
avoids pruning the tip day so its address staging can accumulate. Pruning
here can make subsequent refreshes undercount current-day unique metrics.
Also, the collectData finalization is skipped by the no-new-block early
return.

Refresh the tip day without pruning, finalize only completed days, and run
completed-day finalization even during idle collection cycles.






Also applies to: 1002-1003, 1046-1051

────────────────────────────────────────────────────────────────────────

major [Stability & Availability]
→ ]8;;vscode://file//work/apps/metachronik/src/index.ts:54apps/metachronik/src/index.ts:54-66]8;;

Do not suppress process-level failures based on broad message matches.

Any unhandled error containing "timeout" or "connection error" is
discarded outside the indexing retry loop. This can silently lose
unrelated failed work and leave the process running in an inconsistent
state. Restrict suppression to verified PostgreSQL/network error codes and
terminate gracefully for everything else.






Also applies to: 1140-1158

────────────────────────────────────────────────────────────────────────

major [Data Integrity & Integration]
→ ]8;;vscode://file//work/apps/metachronik/src/index.ts:877apps/metachronik/src/index.ts:877-880]8;;

The committed-tip resync prevents historical gap repair.

detectAndFillGaps() passes a historical gap start, but Line 878
immediately advances it to highestBlockHeight + 1. The gap remains
missing while the caller reports success. Ordered UTXO/token events also
cannot safely be inserted behind already-applied state; use a dedicated
rollback/replay repair workflow or fail with a required reindex.

────────────────────────────────────────────────────────────────────────

major [Stability & Availability]
→ ]8;;vscode://file//work/apps/metachronik/src/index.ts:779apps/metachronik/src/index.ts:779-810]8;;

Propagate deterministic transformation failures.

Every transformBlockData exception becomes a failed batch that is
retried forever. A malformed block or code defect will permanently stall
the indexer at the same range. Preserve the original error classification
and retry only explicit transient transport failures; rethrow all others.






Also applies to: 908-921

────────────────────────────────────────────────────────────────────────

major [Stability & Availability]
→ ]8;;vscode://file//work/web/charts.e.cash/src/lib/chartQueryParams.ts:30web/charts.e.cash/src/lib/chartQueryParams.ts:30-38]8;;

Uncaught RangeError for regex-valid but impossible calendar dates.

new Date(...) on a string like 2025-02-30T00:00:00.000Z produces an
Invalid Date in V8 (not a rolled-over date), and calling .toISOString()
on an Invalid Date throws RangeError: Invalid time value. Since
isValidIsoDate doesn't check validity before calling .toISOString(),
any caller passing an out-of-range but regex-matching date (e.g.
start_date=2025-02-30) will throw here instead of returning false,
propagating an uncaught exception up through parseOptionalDateRange into
the API route.


🐛 Proposed fix

 function isValidIsoDate(value: string): boolean {
     if (!ISO_DATE_RE.test(value)) {
         return false;
     }
-    return (
-        new Date(`${value}T00:00:00.000Z`).toISOString().slice(0, 10) === value
-    );
+    const date = new Date(`${value}T00:00:00.000Z`);
+    if (Number.isNaN(date.getTime())) {
+        return false;
+    }
+    return date.toISOString().slice(0, 10) === value;
 }

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/apps/metachronik/src/services/__tests__/new-metrics.test.ts:198apps/metachronik/src/services/__tests__/new-metrics.test.ts:198-200]8;;

Make the BUY and CANCEL fixtures exercise different flags.

Both 5151 and 5100 have 0x51 as their second-to-last opcode, while
the tests claim this position distinguishes BUY from CANCEL. Correct the
fixture or comments so the cancellation branch is genuinely covered.






Also applies to: 290-304

────────────────────────────────────────────────────────────────────────

major [Data Integrity & Integration]
→ ]8;;vscode://file//work/apps/metachronik/src/scripts/checkIndexing.ts:483apps/metachronik/src/scripts/checkIndexing.ts:483-515]8;;

Detect balances remaining after all token UTXOs disappear.

If token_utxos is empty but token_balances contains stale or negative
rows, this branch reports “none yet” and skips every balance invariant.
Mark nonzero balance rows or totals as critical before treating this as an
uninitialized state.

────────────────────────────────────────────────────────────────────────

major [Data Integrity & Integration]
→ ]8;;vscode://file//work/apps/metachronik/src/scripts/repairKnownDrift.ts:54apps/metachronik/src/scripts/repairKnownDrift.ts:54-136]8;;

Prevent concurrent indexing during this repair.

The drift snapshot is collected before BEGIN; an active indexer can
modify the address or UTXOs before the unconditional subtraction,
corrupting an otherwise valid balance. Acquire the indexer’s shared
advisory lock—or require it to be stopped—and revalidate the drift inside
the transaction before updating.

────────────────────────────────────────────────────────────────────────

major [Functional Correctness]
→ ]8;;vscode://file//work/apps/metachronik/src/scripts/checkIndexing.ts:285apps/metachronik/src/scripts/checkIndexing.ts:285-322]8;;

Treat offsetting per-script drift as critical.

When script-level discrepancies cancel globally, fullViolations > 0 but
totals match, so hadCriticalFailure remains false and the script exits
with warning code 1 instead of critical code 2.


Proposed fix

 const fullViolations = BigInt(driftRow.violations ?? 0);
+if (fullViolations > 0n) {
+    hadCriticalFailure = true;
+}
 const driftSats = BigInt(driftRow.drift_sats ?? 0);
...
-            if (fullViolations > 0n) {
-                hadCriticalFailure = true;
-            }

────────────────────────────────────────────────────────────────────────

major [Stability & Availability]
→ ]8;;vscode://file//work/apps/metachronik/src/scripts/checkIndexing.ts:517apps/metachronik/src/scripts/checkIndexing.ts:517-538]8;;

Keep token sums numeric throughout this query. The ::text casts make
COALESCE(..., 0) resolve text vs integer, which PostgreSQL won’t
match, and the final ::bigint drops the overflow protection you get from
SUM(bigint) returning numeric. Use numeric end-to-end here.

────────────────────────────────────────
Review complete
23 findings ✔

Major 17
Minor 6

55 files reviewed:

  • apps/metachronik/PERFORMANCE_OPTIMIZATION.md
  • apps/metachronik/README.md
  • apps/metachronik/env.example
  • apps/metachronik/package.json
  • apps/metachronik/scripts/README.md
  • apps/metachronik/src/database/connection.ts
  • apps/metachronik/src/database/schema.sql
  • apps/metachronik/src/index.ts
  • apps/metachronik/src/scripts/checkIndexing.ts
  • apps/metachronik/src/scripts/repairEmptyScriptUtxos.ts

... and 45 more files
────────────────────────────────────────

Print all AI prompts: coderabbit review --show-prompts

Tail of the build log:

 WARN  GET https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001787.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.335.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/semver/-/semver-6.3.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/debug/-/debug-4.4.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/ms/-/ms-2.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/json5/-/json5-2.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/commander/-/commander-6.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
Progress: resolved 1014, reused 0, downloaded 988, added 989
 WARN  GET https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001787.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.335.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/semver/-/semver-6.3.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/debug/-/debug-4.4.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/ms/-/ms-2.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/json5/-/json5-2.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/commander/-/commander-6.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 ERR_SOCKET_TIMEOUT  request to https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz failed, reason: Socket timeout

FetchError: request to https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz failed, reason: Socket timeout
    at ClientRequest.<anonymous> (/root/.cache/node/corepack/v1/pnpm/10.24.0/dist/pnpm.cjs:41976:18)
    at ClientRequest.emit (node:events:519:28)
    at emitErrorEvent (node:_http_client:107:11)
    at TLSSocket.socketErrorListener (node:_http_client:574:5)
    at TLSSocket.emit (node:events:531:35)
    at emitErrorNT (node:internal/streams/destroy:170:8)
    at emitErrorCloseNT (node:internal/streams/destroy:129:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:90:21)
Build ecash-parse-tests failed with exit code 1

Tail of the build log:

 WARN  GET https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/debug/-/debug-4.4.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/ms/-/ms-2.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/json5/-/json5-2.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/commander/-/commander-6.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.18.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/semver/-/semver-6.3.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/debug/-/debug-4.4.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/ms/-/ms-2.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/json5/-/json5-2.2.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/commander/-/commander-6.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
Progress: resolved 1014, reused 0, downloaded 994, added 994
Progress: resolved 1014, reused 0, downloaded 995, added 996
Progress: resolved 1014, reused 0, downloaded 996, added 996
Progress: resolved 1014, reused 0, downloaded 998, added 999
Progress: resolved 1014, reused 0, downloaded 999, added 999
Progress: resolved 1014, reused 0, downloaded 999, added 1000
Progress: resolved 1014, reused 0, downloaded 1000, added 1000
Progress: resolved 1014, reused 0, downloaded 1000, added 1001
Progress: resolved 1014, reused 0, downloaded 1001, added 1001
Progress: resolved 1014, reused 0, downloaded 1001, added 1002
Progress: resolved 1014, reused 0, downloaded 1002, added 1002
Progress: resolved 1014, reused 0, downloaded 1003, added 1004
Progress: resolved 1014, reused 0, downloaded 1004, added 1004
Progress: resolved 1014, reused 0, downloaded 1004, added 1005
Progress: resolved 1014, reused 0, downloaded 1005, added 1005
 ERR_SOCKET_TIMEOUT  request to https://registry.npmjs.org/debug/-/debug-4.4.3.tgz failed, reason: Socket timeout

FetchError: request to https://registry.npmjs.org/debug/-/debug-4.4.3.tgz failed, reason: Socket timeout
    at ClientRequest.<anonymous> (/root/.cache/node/corepack/v1/pnpm/10.24.0/dist/pnpm.cjs:41976:18)
    at ClientRequest.emit (node:events:519:28)
    at emitErrorEvent (node:_http_client:107:11)
    at TLSSocket.socketErrorListener (node:_http_client:574:5)
    at TLSSocket.emit (node:events:531:35)
    at emitErrorNT (node:internal/streams/destroy:170:8)
    at emitErrorCloseNT (node:internal/streams/destroy:129:3)
    at processTicksAndRejections (node:internal/process/task_queues:90:21)
    at runNextTicks (node:internal/process/task_queues:69:3)
    at listOnTimeout (node:internal/timers:549:9)
Build mock-chronik-client-tests failed with exit code 1

Tail of the build log:

Progress: resolved 1651, reused 97, downloaded 1518, added 1631
 WARN  GET https://registry.npmjs.org/express/-/express-5.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/router/-/router-2.2.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/send/-/send-1.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
Progress: resolved 1651, reused 97, downloaded 1519, added 1631
Progress: resolved 1651, reused 97, downloaded 1519, added 1632
 WARN  GET https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/router/-/router-2.2.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/send/-/send-1.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
Progress: resolved 1651, reused 97, downloaded 1520, added 1632
Progress: resolved 1651, reused 97, downloaded 1520, added 1633
Progress: resolved 1651, reused 97, downloaded 1521, added 1633
Progress: resolved 1651, reused 97, downloaded 1521, added 1634
Progress: resolved 1651, reused 97, downloaded 1522, added 1634
Progress: resolved 1651, reused 97, downloaded 1525, added 1638
Progress: resolved 1651, reused 97, downloaded 1526, added 1638
Progress: resolved 1651, reused 97, downloaded 1527, added 1640
 ERR_SOCKET_TIMEOUT  request to https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz failed, reason: Socket timeout

FetchError: request to https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz failed, reason: Socket timeout
    at ClientRequest.<anonymous> (/root/.cache/node/corepack/v1/pnpm/10.24.0/dist/pnpm.cjs:41976:18)
    at ClientRequest.emit (node:events:519:28)
    at emitErrorEvent (node:_http_client:107:11)
    at TLSSocket.socketErrorListener (node:_http_client:574:5)
    at TLSSocket.emit (node:events:531:35)
    at emitErrorNT (node:internal/streams/destroy:170:8)
    at emitErrorCloseNT (node:internal/streams/destroy:129:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:90:21)
Build chronik-client-tests failed with exit code 1

Tail of the build log:

 WARN  GET https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
Progress: resolved 2665, reused 0, downloaded 2531, added 2645
Progress: resolved 2665, reused 0, downloaded 2531, added 2646
 WARN  GET https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
Progress: resolved 2665, reused 0, downloaded 2532, added 2646
Progress: resolved 2665, reused 0, downloaded 2533, added 2648
Progress: resolved 2665, reused 0, downloaded 2534, added 2648
Progress: resolved 2665, reused 0, downloaded 2535, added 2650
Progress: resolved 2665, reused 0, downloaded 2536, added 2650
Progress: resolved 2665, reused 0, downloaded 2536, added 2651
Progress: resolved 2665, reused 0, downloaded 2537, added 2652
Progress: resolved 2665, reused 0, downloaded 2538, added 2652
Progress: resolved 2665, reused 0, downloaded 2539, added 2654
Progress: resolved 2665, reused 0, downloaded 2540, added 2654
Progress: resolved 2665, reused 0, downloaded 2541, added 2656
Progress: resolved 2665, reused 0, downloaded 2542, added 2656
Progress: resolved 2665, reused 0, downloaded 2542, added 2657
Progress: resolved 2665, reused 0, downloaded 2543, added 2657
Progress: resolved 2665, reused 0, downloaded 2543, added 2658
Progress: resolved 2665, reused 0, downloaded 2544, added 2658
Progress: resolved 2665, reused 0, downloaded 2544, added 2659
Progress: resolved 2665, reused 0, downloaded 2545, added 2659
Progress: resolved 2665, reused 0, downloaded 2545, added 2660
 ERR_SOCKET_TIMEOUT  request to https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz failed, reason: Socket timeout

FetchError: request to https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz failed, reason: Socket timeout
    at ClientRequest.<anonymous> (/root/.cache/node/corepack/v1/pnpm/10.24.0/dist/pnpm.cjs:41976:18)
    at ClientRequest.emit (node:events:519:28)
    at emitErrorEvent (node:_http_client:107:11)
    at TLSSocket.socketErrorListener (node:_http_client:574:5)
    at TLSSocket.emit (node:events:531:35)
    at emitErrorNT (node:internal/streams/destroy:170:8)
    at emitErrorCloseNT (node:internal/streams/destroy:129:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:90:21)
Build ecashaddrjs-tests failed with exit code 1

Tail of the build log:

 WARN  GET https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 10 seconds. 2 retries left.
 WARN  GET https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
 WARN  GET https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz error (ERR_SOCKET_TIMEOUT). Will retry in 1 minute. 1 retries left.
Progress: resolved 2665, reused 0, downloaded 2532, added 2646
Progress: resolved 2665, reused 0, downloaded 2532, added 2647
Progress: resolved 2665, reused 0, downloaded 2533, added 2647
Progress: resolved 2665, reused 0, downloaded 2533, added 2648
Progress: resolved 2665, reused 0, downloaded 2534, added 2648
Progress: resolved 2665, reused 0, downloaded 2534, added 2649
Progress: resolved 2665, reused 0, downloaded 2535, added 2649
Progress: resolved 2665, reused 0, downloaded 2537, added 2652
Progress: resolved 2665, reused 0, downloaded 2538, added 2652
Progress: resolved 2665, reused 0, downloaded 2539, added 2654
Progress: resolved 2665, reused 0, downloaded 2540, added 2654
Progress: resolved 2665, reused 0, downloaded 2543, added 2658
Progress: resolved 2665, reused 0, downloaded 2544, added 2658
Progress: resolved 2665, reused 0, downloaded 2544, added 2659
Progress: resolved 2665, reused 0, downloaded 2545, added 2659
Progress: resolved 2665, reused 0, downloaded 2547, added 2662
 ERR_SOCKET_TIMEOUT  request to https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz failed, reason: Socket timeout

FetchError: request to https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz failed, reason: Socket timeout
    at ClientRequest.<anonymous> (/root/.cache/node/corepack/v1/pnpm/10.24.0/dist/pnpm.cjs:41976:18)
    at ClientRequest.emit (node:events:519:28)
    at emitErrorEvent (node:_http_client:107:11)
    at TLSSocket.socketErrorListener (node:_http_client:574:5)
    at TLSSocket.emit (node:events:531:35)
    at emitErrorNT (node:internal/streams/destroy:170:8)
    at emitErrorCloseNT (node:internal/streams/destroy:129:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:90:21)
Build cashtab-connect-tests failed with exit code 1

Build Bitcoin ABC Diffs / Diff Testing (ai-review) passed.
CodeRabbit Review

Diff : committed changes only
Compare : HEAD → master
Directory : work
────────────────────────────────────────

(\(\
(• .•) Deploying the charm offensive against your bugs.

────────────────────────────────────────────────────────────────────────

major [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/app/api/charts/token-rich-list/route.ts:37web/charts.e.cash/src/app/api/charts/token-rich-list/route.ts:37-50]8;;

Preserve min_atoms=0 for mint-baton queries.

min_atoms=0 is clamped to 1, so the documented
include_mint_batons=true&min_atoms=0 request still excludes all
zero-atom batons.






Proposed fix

-            minAtoms = parsedMinAtoms < BigInt(1) ? BigInt(1) : parsedMinAtoms;
+            minAtoms = parsedMinAtoms < BigInt(0) ? BigInt(1) : parsedMinAtoms;

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/lib/chartQueryParams.ts:9web/charts.e.cash/src/lib/chartQueryParams.ts:9-26]8;;

fallback isn't clamped to [min, max].

if (value === null || value === '') { return fallback; } returns
fallback verbatim, unlike the parsed-value path which clamps via
Math.min(max, Math.max(min, parsed)) (Line 25). If a caller ever passes
a fallback outside [min, max], the "bounded" contract silently breaks
for the missing/empty-param case.


🛡️ Proposed fix

     if (value === null || value === '') {
-        return fallback;
+        return Math.min(max, Math.max(min, fallback));
     }

────────────────────────────────────────
Review complete
2 findings ✔

Major 1
Minor 1

55 files reviewed:

  • apps/metachronik/PERFORMANCE_OPTIMIZATION.md
  • apps/metachronik/README.md
  • apps/metachronik/env.example
  • apps/metachronik/package.json
  • apps/metachronik/scripts/README.md
  • apps/metachronik/src/database/connection.ts
  • apps/metachronik/src/database/schema.sql
  • apps/metachronik/src/index.ts
  • apps/metachronik/src/scripts/checkIndexing.ts
  • apps/metachronik/src/scripts/repairEmptyScriptUtxos.ts

... and 45 more files
────────────────────────────────────────

Print all AI prompts: coderabbit review --show-prompts

Rebase onto latest master so pnpm-lock.yaml matches CI base.

Build Bitcoin ABC Diffs / Diff Testing (ai-review) passed.
CodeRabbit Review

Diff : committed changes only
Compare : HEAD → master
Directory : work
────────────────────────────────────────

(\(\
(• .•) This is what it sounds like when bugs cry.

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/app/api/charts/token-rich-list/route.ts:29web/charts.e.cash/src/app/api/charts/token-rich-list/route.ts:29-50]8;;

Permit the documented min_atoms=0 baton request.

min_atoms=0 is clamped to 1, so the request described in the adjacent
contract cannot be made. Parse include_mint_batons first and retain zero
only when it is enabled.


Proposed fix

+        const includeMintBatons =
+            searchParams.get('include_mint_batons') === 'true';
+
         let minAtoms: bigint;
         const minAtomsRaw = searchParams.get('min_atoms');
         try {
@@
             }
             const parsedMinAtoms = BigInt(minAtomsRaw || '1');
-            minAtoms = parsedMinAtoms < BigInt(1) ? BigInt(1) : parsedMinAtoms;
+            if (
+                parsedMinAtoms < BigInt(0) ||
+                (parsedMinAtoms === BigInt(0) && !includeMintBatons)
+            ) {
+                throw new Error('invalid');
+            }
+            minAtoms = parsedMinAtoms;
         } catch {
@@
-        const includeMintBatons =
-            searchParams.get('include_mint_batons') === 'true';

────────────────────────────────────────────────────────────────────────

major [Stability & Availability]
→ ]8;;vscode://file//work/apps/metachronik/package.json:9apps/metachronik/package.json:9-11]8;;

Do not allow the Node heap limit to consume the entire 8 GB host.

The documented deployment target has 8 GB total RAM, but these scripts
permit an 8192 MB V8 heap before accounting for native allocations,
PostgreSQL, and the OS. This can turn memory pressure into host-level OOM
kills. Align the limit with the documented 4096 MB guidance, or make it
deployment-specific.


Proposed adjustment

-        "start": "node --max-old-space-size=8192 dist/index.js 2>&1 | ts",
-        "dev": "NODE_OPTIONS='--max-old-space-size=8192' ts-node src/index.ts",
-        "dev:reindex": "NODE_OPTIONS='--max-old-space-size=8192' ts-node src/index.ts --reindex",
+        "start": "node --max-old-space-size=4096 dist/index.js",
+        "dev": "NODE_OPTIONS='--max-old-space-size=4096' ts-node src/index.ts",
+        "dev:reindex": "NODE_OPTIONS='--max-old-space-size=4096' ts-node src/index.ts --reindex",

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/web/charts.e.cash/src/config/chartOptions.ts:259web/charts.e.cash/src/config/chartOptions.ts:259-262]8;;

Zoom max may clip the daily_active_addresses line.

With sumFields unset, the zoom/max calculation uses only the first field
(daily_active_senders). Since active addresses (sent or received) is
always ≥ active senders, deriving the y-domain from senders will clip the
taller daily_active_addresses line. List the larger series first so the
domain covers both.






🔧 Proposed fix

         dataConfig: {
             dataKey: 'completeDailyActiveAddresses',
-            fields: ['daily_active_senders', 'daily_active_addresses'],
+            fields: ['daily_active_addresses', 'daily_active_senders'],
         },

────────────────────────────────────────────────────────────────────────

minor [Data Integrity & Integration]
→ ]8;;vscode://file//work/web/charts.e.cash/src/lib/database.ts:1419web/charts.e.cash/src/lib/database.ts:1419-1441]8;;

getIndexedTokens skips the Number() coercion applied everywhere else.

Every other method in this file explicitly coerces numeric fields with
Number(...) before returning, since Postgres returns BIGINT/NUMERIC
columns as JS strings. getIndexedTokens returns result.rows raw, so
first_seen_height will likely come back as a string while every other
endpoint's numeric fields come back as numbers — an inconsistent API
contract for consumers of this method.


🛠️ Suggested fix

             const params = protocol ? [limit, protocol] : [limit];
             const result = await client.query(query, params);
-            return result.rows;
+            return result.rows.map(
+                (row: {
+                    token_id: string;
+                    token_protocol: string;
+                    token_type: string;
+                    first_seen_height: string | number;
+                }) => ({
+                    ...row,
+                    first_seen_height: Number(row.first_seen_height),
+                }),
+            );

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/apps/metachronik/src/scripts/checkIndexing.ts:125apps/metachronik/src/scripts/checkIndexing.ts:125-141]8;;

ts_utc rendering can be shifted by the Node process timezone.

to_timestamp(timestamp) AT TIME ZONE 'UTC' yields a `timestamp without
time zone, which node-postgres parses using the local timezone. new
Date(r.ts_utc).toISOString()` therefore prints a shifted time unless the
process runs in UTC. Since the unix timestamp is already selected,
derive the instant directly instead.





🕒 Proposed fix

-        const latest = await pool.query(
-            `SELECT height, timestamp,
-                    to_timestamp(timestamp) AT TIME ZONE 'UTC' AS ts_utc
-             FROM blocks
+        const latest = await pool.query(
+            `SELECT height, timestamp
+             FROM blocks
             ORDER BY height DESC
             LIMIT 1`,
         );
         if (latest.rows.length > 0) {
             const r = latest.rows[0];
             line(
                 'INFO',
                 'Latest block',
-                `height ${Number(r.height).toLocaleString()} at ${new Date(
-                    r.ts_utc,
-                ).toISOString()}`,
+                `height ${Number(r.height).toLocaleString()} at ${new Date(
+                    Number(r.timestamp) * 1000,
+                ).toISOString()}`,
             );
         }

────────────────────────────────────────────────────────────────────────

minor [Functional Correctness]
→ ]8;;vscode://file//work/apps/metachronik/src/scripts/repairEmptyScriptUtxos.ts:170apps/metachronik/src/scripts/repairEmptyScriptUtxos.ts:170-177]8;;

Convert row.sats to a string before binding it. pg doesn’t accept
bigint query parameters directly, so passing row.sats can fail during
serialization and abort this repair job.

────────────────────────────────────────
Review complete
6 findings ✔

Major 1
Minor 5

55 files reviewed:

  • apps/metachronik/PERFORMANCE_OPTIMIZATION.md
  • apps/metachronik/README.md
  • apps/metachronik/env.example
  • apps/metachronik/package.json
  • apps/metachronik/scripts/README.md
  • apps/metachronik/src/database/connection.ts
  • apps/metachronik/src/database/schema.sql
  • apps/metachronik/src/index.ts
  • apps/metachronik/src/scripts/checkIndexing.ts
  • apps/metachronik/src/scripts/repairEmptyScriptUtxos.ts

... and 45 more files
────────────────────────────────────────

Print all AI prompts: coderabbit review --show-prompts

This revision is now accepted and ready to land.Wed, Jul 22, 13:15