Skip to content

feat: add the Sapphire testnet - #199

Merged
moul merged 2 commits into
mainfrom
feat/sapphire-testnet
Aug 9, 2026
Merged

feat: add the Sapphire testnet#199
moul merged 2 commits into
mainfrom
feat/sapphire-testnet

Conversation

@moul

@moul moul commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Adds Sapphire to the network registry. Topaz stays the default — a new
network should be selectable, not imposed on anyone mid-session.

One correction to the announced endpoints

The announcement gives the tx-indexer as
https://indexer.sapphire.testnets.gno.land/graphql. That path serves the
GraphQL playground — an HTML page.
Pointing the app at it would have fed
markup to a JSON parser, surfacing as the "returned a non-JSON response"
error rather than anything that names the real cause.

The API is /graphql/query, the same convention Topaz already uses:

POST .../graphql       → 200 text/html   "<!DOCTYPE html> … GraphQL playground"
POST .../graphql/query → 200 {"data":{"latestBlockHeight":32176}}

There's a regression test pinning the /graphql/query suffix.

Everything verified live, not assumed

RPC sapphire-1, v1.0.0-rc.0, height 32k+
Indexer access-control-allow-origin: * — ADR-018 holds here too
Indexer schema all four message types present (BankMsgSend, MsgCall, MsgAddPackage, MsgRun) across 48 txs
gnoweb / gnockpit / status 200, real deployments confirmed by page title
explorer not in the announcement, but deployed and serving real mygnoscan — included

Then end-to-end in the app against the live chain:

  • Island reads Sapphire (official testnet), live height ticking.
  • Block Explorer on block 32010 renders "Sent 300 GNOT" with from, to,
    fee and hash — 300 being one of the announced faucet drips. This exercises
    yesterday's blockTransactions query against a second indexer, which is
    the main thing that could have differed.
  • Realms 32, Developer libraries 58 — matching a direct vm/qpaths
    probe exactly, so the split holds on a chain with a very different mix
    from Topaz's 196/145.

persistence: "rolling"

Assumed, matching Topaz. Nothing in the announcement states a retention
policy, and rolling is the conservative claim — it warns that history may
not go back forever rather than promising it does. Worth correcting if the
real policy is known.

Why an e2e test changed

custom-network-probe.spec.ts asserted the network dropdown had exactly 3
options. Its actual intent is "the bogus endpoint was not added"; the
literal made it a second, accidental assertion about how many networks ship
by default, which a fourth network breaks. It now captures the count before
the attempt and asserts it is unchanged — same intent, and it won't break
on the next testnet.

Gates

typecheck, lint, 467 web unit tests (+7 in @gnomputer/networks), build,
88 e2e. Bundle 383.2KB / 388KB.

moul added 2 commits August 9, 2026 14:18
Vetting Sapphire's indexer meant editing a hardcoded NETWORK constant to
point the checks at it and then remembering to put it back. The next
network should not need that:

  LIVE_INDEXER=1 LIVE_INDEXER_ID=sapphire \
  LIVE_INDEXER_URL=https://indexer.sapphire.testnets.gno.land/graphql/query \
  pnpm --filter @gnomputer/rpc exec vitest run src/live-schema-check.test.ts

All six checks pass against Sapphire, which is the evidence behind the
indexer.read capability in this PR. A newly launched chain is exactly where
this earns its keep: a field the indexer has not started emitting yet reads
identically to one it never will, and both break parsing the same way.
@moul
moul merged commit 79d0c57 into main Aug 9, 2026
9 checks passed
@moul
moul deleted the feat/sapphire-testnet branch August 9, 2026 12:24
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.

1 participant