Skip to content

fix(explorer): fix token holder count for high-volume tokens like PathUSD#789

Open
decofe wants to merge 3 commits intomainfrom
omar/fix-pathusd-holders-count
Open

fix(explorer): fix token holder count for high-volume tokens like PathUSD#789
decofe wants to merge 3 commits intomainfrom
omar/fix-pathusd-holders-count

Conversation

@decofe
Copy link
Copy Markdown
Member

@decofe decofe commented Mar 27, 2026

Summary

PathUSD shows 0 holders on the tokens list page while USDC.e was undercounted at 3,168 (correct count: ~7,942).

Motivation

The token holder count query used GROUP BY (from, to) to aggregate Transfer events, producing one row per unique transfer pair. For high-volume tokens, this creates far more rows than tidx's 10,000-row hard limit. The query silently truncates, and the incomplete data aggregates to incorrect holder counts.

Changes

  • Split the single GROUP BY (from, to) query into two separate queries: one for received amounts (GROUP BY to) and one for sent amounts (GROUP BY from)
  • Row count drops from O(unique_transfer_pairs) to O(unique_senders + unique_receivers)
  • Updated both fetchTokenHolderBalances (single token) and fetchTokenHoldersCountRows (batch)
  • Updated unit tests to match the new two-query pattern

Results

USDC.e holders: 3,168 → 7,942 (correct count restored)

PathUSD still shows 0 because it has >10k unique senders (every tx on Tempo pays fees in PathUSD). Fixing this fully requires raising tidx's hard limit or adding server-side pagination support in tidx.

Screenshots

Before (production) After (preview)
USDC.e: 3,168 holders USDC.e: 7,942 holders
PathUSD: 0 holders PathUSD: 0 holders (>10k unique senders)

Preview URL: https://15d92daa-explorer-mainnet.porto.workers.dev/tokens

Testing

  • Type check: pnpm check:types passes
  • Lint/format: pnpm check passes
  • Unit tests updated for new query structure

Prompted by: omar

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 27, 2026

Bundle Size Report

Metric Size Δ Change
Total 4.1 MB -673.0 KB (-13.7%)
Gzip 1.2 MB -110.1 KB (-8.3%)
Brotli 1.0 MB -88.4 KB (-7.7%)
Chunk changes (>1KB)
Chunk Change
assets/KeyManager.js (removed) -477.4 KB
assets/QueryBuilder.js (removed) -423.4 KB
assets/router.js -303.0 KB
assets/wagmi.config.js -166.8 KB
assets/_hash.js -128.9 KB
assets/BaseTanStackRouterDevtoolsPanel-Bmws3ikM.js (removed) -99.5 KB
assets/Intro.js (removed) -66.0 KB
assets/createSsrRpc.js (removed) -43.8 KB
assets/isAddressEqual.js -32.5 KB
assets/path.js (removed) -30.6 KB
assets/FloatingTanStackRouterDevtools-B7vy70jP.js (removed) -24.4 KB
assets/_layout.js -21.4 KB
assets/stringify.js (removed) -19.7 KB
assets/Hash.js -16.4 KB
assets/address.js -14.1 KB
assets/getAction.js -13.0 KB
assets/base.js (removed) -12.8 KB
assets/utils.js -10.1 KB
assets/token.server.js (removed) -9.8 KB
assets/Address.js -9.7 KB
...and 36 more

Compared against main branch (baseline from 2/4/2026, 5:13:51 PM)

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 27, 2026

Cloudflare Deployments

App Environment Status Preview
explorer devnet [OK] Deployed View Preview
explorer mainnet [OK] Deployed View Preview
explorer testnet [OK] Deployed View Preview
fee-payer devnet [>>] Skipped No changes
fee-payer moderato [>>] Skipped No changes
fee-payer privy [>>] Skipped No changes
og - [>>] Skipped No changes
tokenlist - [>>] Skipped No changes

@o-az
Copy link
Copy Markdown
Member

o-az commented Mar 27, 2026

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

decofe and others added 3 commits March 28, 2026 11:31
…hUSD

Replace GROUP BY (from, to) with two separate queries grouped by
individual holder (GROUP BY to for received, GROUP BY from for sent).
This reduces row count from O(unique_transfer_pairs) to
O(unique_holders), avoiding truncation by tidx's 10k row hard limit.

Co-authored-by: o-az <23618431+o-az@users.noreply.github.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019d2c9a-d957-714c-add1-f823c928ddfe
PathUSD has more unique senders than tidx's 10k row limit, so even with
the GROUP BY holder fix, results were still truncated. Add a fetchAllPages
helper that paginates through the limit using LIMIT/OFFSET.

Co-authored-by: o-az <23618431+o-az@users.noreply.github.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019d2c9a-d957-714c-add1-f823c928ddfe
The LIMIT/OFFSET approach causes tidx to return empty results for all
tokens, likely due to interaction with the CTE-based query rewriting.
The GROUP BY holder fix alone already fixes most tokens (USDC.e went
from 3,168 to 7,943 holders). PathUSD still needs a tidx-side fix for
tokens with >10k unique senders.

Co-authored-by: o-az <23618431+o-az@users.noreply.github.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019d2c9a-d957-714c-add1-f823c928ddfe
@o-az o-az force-pushed the omar/fix-pathusd-holders-count branch from d07408b to eaf2d02 Compare March 28, 2026 18:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants