You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
5. Supporting modules — src/config/zcashConstants.ts, src/utils/zcashFormatters.ts / zcashUtils.ts, src/hooks/useZcashDashboard.ts, and Zcash branches in useSearch.ts, useNetworkDashboard.ts, NavbarLogo.tsx, NetworkBlockIndicator.tsx, DataService.ts, AIPromptTemplates.ts, settings/index.tsx, plus locales/*/tooltips.json for all five languages.
What Zcash needs that Bitcoin does not
These are the parts where copying BitcoinAdapter verbatim will be wrong:
hash_or_height is a string.getBlock, getBlockHeader and zGetTreestate take a block hash or a height as a decimal string — getBlock("3444000", 1), not a number. Easy to get wrong when porting Bitcoin call sites.
getRawTransaction verbosity is numeric (0 = hex, 1 = object), not a boolean as in Bitcoin.
Address-index methods take an object bag: getAddressBalance({ addresses: ["t1..."] }).
Zcash-only response fields to surface in the UI: nonce is a 32-byte hex string (not a number), solution holds the Equihash solution, blocks carry finalsaplingroot / finalorchardroot (the latter only on post-NU5 blocks, so treat it as optional) and trees (Sapling/Orchard note-commitment tree sizes).
Shielded transaction bundles: transactions may carry vShieldedSpend, vShieldedOutput, an orchard bundle, valueBalance, and vjoinsplit for Sprout-era transactions. A transaction can legitimately have empty vin/vout while moving value entirely within a shielded pool — the transaction view must not render those as "empty".
Address types: transparent (t1…/t3…), Sapling (zs…), and unified (u1…). Search and address routing need to distinguish them; zListUnifiedReceivers decomposes a unified address into its receivers.
Value pools on the dashboard: getBlockchainInfo returns per-pool balances (transparent, sprout, sapling, orchard, lockbox, ironwood) plus chainSupply — good material for the network dashboard, and genuinely Zcash-specific.
Constraints worth knowing before starting
No WebSocket. Zebra's RPC server is built .http_only(), so there are no subscriptions. Live block updates must poll, as Bitcoin already does.
Hosted RPC cannot serve the shielded features. The only free endpoints (Tatum) whitelist their method set: every z_* and getaddress* call returns -32601, with or without an API key — I verified this against a real key, so it is a fixed whitelist rather than a paid tier. That means address balance/history pages and any shielded-pool view require a self-hosted zebrad. See feat: add Zcash to explorer-metadata #397.
Suggested sequencing: ship blocks / transactions / mempool / block dashboard against the hosted endpoints first, and gate the address and shielded views behind the self-hosted node.
Acceptance Criteria
NetworkType includes "zcash"
ZcashAdapter implemented and registered in adaptersFactory.ts
pages/zcash/ renders network, blocks, block, txs, tx and mempool views
zec / tzec routes registered before the :networkId catch-all
Search resolves Zcash block hashes, heights, txids and transparent addresses
Shielded transactions render correctly, including ones with empty vin/vout
Tooltip locales added for all five languages
Address and shielded views degrade gracefully when the RPC rejects the method
Summary
Add Zcash as a first-class network in the explorer UI — adapter, pages, routes and search — mirroring how Bitcoin is wired up.
Motivation
Completes the Zcash rollout. Depends on #396 (ships
ZcashClient) and #397 (network entries +type: "zcash").Proposed Solution
Bitcoin is the closest existing template, since Zcash is a Bitcoin fork with a UTXO model plus shielded pools.
1. Types —
src/types/index.ts: widenNetworkTypefrom"evm" | "bitcoin" | "solana"to include"zcash".2. Adapter —
src/services/adapters/ZcashAdapter/ZcashAdapter.ts, modelled onBitcoinAdapter. Add acreateZcashAdapter(networkId: string, client: ZcashClient)branch toadaptersFactory.tsalongsidecreateBitcoinAdapter.3. Pages —
src/components/pages/zcash/, mirroringpages/bitcoin/: network dashboard, blocks list + detail, transactions list + detail, address, mempool. Register lazy exports inLazyComponents.tsx.4. Routes —
App.tsx, following thebtc/tbtcpattern and keeping them before the:networkIdcatch-all:plus the
tzectestnet equivalents.5. Supporting modules —
src/config/zcashConstants.ts,src/utils/zcashFormatters.ts/zcashUtils.ts,src/hooks/useZcashDashboard.ts, and Zcash branches inuseSearch.ts,useNetworkDashboard.ts,NavbarLogo.tsx,NetworkBlockIndicator.tsx,DataService.ts,AIPromptTemplates.ts,settings/index.tsx, pluslocales/*/tooltips.jsonfor all five languages.What Zcash needs that Bitcoin does not
These are the parts where copying
BitcoinAdapterverbatim will be wrong:hash_or_heightis a string.getBlock,getBlockHeaderandzGetTreestatetake a block hash or a height as a decimal string —getBlock("3444000", 1), not a number. Easy to get wrong when porting Bitcoin call sites.getRawTransactionverbosity is numeric (0= hex,1= object), not a boolean as in Bitcoin.getAddressBalance({ addresses: ["t1..."] }).nonceis a 32-byte hex string (not a number),solutionholds the Equihash solution, blocks carryfinalsaplingroot/finalorchardroot(the latter only on post-NU5 blocks, so treat it as optional) andtrees(Sapling/Orchard note-commitment tree sizes).vShieldedSpend,vShieldedOutput, anorchardbundle,valueBalance, andvjoinsplitfor Sprout-era transactions. A transaction can legitimately have emptyvin/voutwhile moving value entirely within a shielded pool — the transaction view must not render those as "empty".t1…/t3…), Sapling (zs…), and unified (u1…). Search and address routing need to distinguish them;zListUnifiedReceiversdecomposes a unified address into its receivers.getBlockchainInforeturns per-pool balances (transparent,sprout,sapling,orchard,lockbox,ironwood) pluschainSupply— good material for the network dashboard, and genuinely Zcash-specific.Constraints worth knowing before starting
.http_only(), so there are no subscriptions. Live block updates must poll, as Bitcoin already does.z_*andgetaddress*call returns-32601, with or without an API key — I verified this against a real key, so it is a fixed whitelist rather than a paid tier. That means address balance/history pages and any shielded-pool view require a self-hostedzebrad. See feat: add Zcash to explorer-metadata #397.Acceptance Criteria
NetworkTypeincludes"zcash"ZcashAdapterimplemented and registered inadaptersFactory.tspages/zcash/renders network, blocks, block, txs, tx and mempool viewszec/tzecroutes registered before the:networkIdcatch-allvin/vout