Skip to content

Update subsquid client to use latest subsquid#109

Merged
n13 merged 2 commits into
mainfrom
beast/update-subsquid-url
Jun 12, 2026
Merged

Update subsquid client to use latest subsquid#109
n13 merged 2 commits into
mainfrom
beast/update-subsquid-url

Conversation

@dewabisma

@dewabisma dewabisma commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary


Note

Medium Risk
Changes default indexer URL and GraphQL schema for wormhole collect-rewards, transfer queries, and nullifier checks; behavior should match prior limits but depends on the new Hasura deployment being correct and in sync.

Overview
Switches the CLI to the new Hasura-backed indexer at https://sub2.quantus.com/v1/graphql by updating default --subsquid-url on transfers query, wormhole collect-rewards, and wormhole check-nullifier, plus matching README docs.

Rewrites SubsquidClient away from custom Subsquid resolvers (transfersByHashPrefix / nullifiersByPrefix) toward Hasura table queries on transfer and wormhole_nullifier, with _like hash-prefix filters, nested block.height, and transfer_aggregate for total counts. The 1000-result cap and error wording are preserved so query_all_transfers_by_prefix still binary-splits block ranges on the same marker.

Adds Hasura row types and mapping (HasuraTransferRow, HasuraNullifierRow) into the existing flat Transfer / NullifierResult types, including flexible deserialization of Postgres numeric fields (JSON number or string) and mapping extrinsic_id / wormholeExtrinsic.extrinsic_id for extrinsic hashes.

Reviewed by Cursor Bugbot for commit 56473a2. Configure here.

@dewabisma dewabisma requested review from illuzen and n13 June 12, 2026 05:52

@n13 n13 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh this is important, didn't realize this - testing

@n13

n13 commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

The review is complete. I checked out the PR branch, audited every GraphQL call site, verified the queries against the live Hasura server, and exercised the redeem path end-to-end. Here's the full picture.

Verdict: the PR is correct and should be merged soon — the old endpoint is already dead

https://subsquid.quantus.com/blue/graphql now returns {"error":"resource does not exist"}, so main is currently broken for all indexer features. This PR is the fix, not just an upgrade.

What I verified against the live server (sub2.quantus.com)

Schema compatibility. I introspected the Hasura schema: all tables (transfer, transfer_aggregate, wormhole_nullifier), columns, and the nested relationships (block { height }, wormholeExtrinsic { extrinsic_id }) used by the new queries exist with matching types. I replayed both exact GraphQL documents from the client with realistic variables — no errors, correct shapes.

Hash compatibility — the make-or-break for redeems. The client filters results by exact hash equality, so a format mismatch would silently return zero transfers. Both formats match:

  • Address hashes: the CLI's transfers hash-address for qzjUYyuN4L3... produces 9515049071ed9131..., byte-identical to that address's from_hash in the new database.
  • Nullifier hashes: for two real spent nullifiers in the database, blake3 of the nullifier bytes exactly equals the stored nullifier_hash. So check_nullifiers_spent will correctly detect spent transfers.

extrinsic_id mapping. Despite the FK-sounding name, the new schema stores the actual extrinsic hash (0x6e03c2...) in extrinsic_id (the extrinsic table has no separate hash field), so mapping it to Transfer.extrinsic_hash is semantically correct.

The 1000-cap emulation and binary-split contract. A broad live query (84,095 matches) produced the error "Query returned 84095 results, which exceeds the limit of 1000..." — same wording the paginator in query_all_transfers_by_prefix splits on, so the redeem discovery path keeps working for heavy addresses. I also confirmed there is no hidden Hasura row cap: a limit-1000 query returns exactly 1000 rows, and an unbounded nullifier query returned all 149,376 rows.

End-to-end CLI runs against the live server, all on the PR branch:

  • wormhole check-nullifier --secret ... --transfer-counts 0-5 — works, reports 6 unspent.
  • wormhole collect-rewards --secret ... --dry-run — works, runs the full redeem query path cleanly.
  • transfers query with a narrow block range — returns and renders real rows correctly (amounts, direction, timestamps, block heights), proving live-data deserialization through HasuraTransferRow.
  • cargo test: 210 tests pass. All 9 CI checks on the PR are green.

Coverage of all GraphQL access. Every GraphQL call goes through SubsquidClient; its three consumers are transfers query, wormhole check-nullifier, and the collect-rewards/redeem flow in collect_rewards_lib.rs (also used by the SDK). No other code touches the indexer, and proof generation takes transfer_count/amount from the on-chain leaf rather than the indexer, so the indexer only affects discovery and spent-filtering — with the on-chain nullifier pre-check still guarding submission.

Non-blocking suggestions

  1. The nullifier query has no limit and no count check (query_nullifiers_by_prefix). Today Hasura returns everything, but if the deployment ever adds an API row limit, results would silently truncate and spent nullifiers would be reported as unspent (caught later by on-chain pre-validation, but it's a silent failure until then). Adding a wormhole_nullifier_aggregate count check, mirroring the transfer query, would fail early.

  2. visit_f64 in numeric_string silently loses precision for values above 2^53 if the server ever stops stringifying numerics (planck amounts can exceed that). Currently moot — the server stringifies all numerics — but returning an error from visit_f64 instead of formatting would be safer.

  3. data.meta.aggregate.map(|a| a.count).unwrap_or(0) treats a missing aggregate as zero; erroring would surface permission regressions instead of masking them.

  4. Minor DRY nit: the _or/_like prefix-condition building is duplicated between build_transfer_where and query_nullifiers_by_prefix and could be a shared helper.

  5. Pre-existing (not from this PR): transfers query uses the non-splitting query path, so an address with more than 1000 lifetime transfers can never be listed regardless of prefix length — two of your local wallets (the planck-tc ones, with 8k–24k transfers) hit this. Same behavior as the old server, just noting it.

Note that I left the beast/update-subsquid-url branch checked out locally, and per your rules I haven't posted anything to GitHub — if you'd like, I can post this review (or an approval) on the PR.

@n13 n13 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should release this

@n13 n13 merged commit 3572fe0 into main Jun 12, 2026
9 checks passed
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