Building Zcash products end-to-end

I think one of the biggest barriers to Zcash adoption is not a shortage of capable software. It is the lack of clear, visible paths showing how the existing pieces work together from a node to a product that people can use.

A Zcash product rarely depends on one repository. An explorer may need a node, an indexer, and a user interface. A wallet or payment service also depends on wallet state, transaction construction, and broadcast.

The ecosystem has strong components, but builders still have too few documented paths connecting them into working products, and when the layers are validated separately, it is hard to see which combinations work or reproduce failures between them. In the simplest form, I think Testnet should make those paths visible. A developer should be able to follow a real flow from the node, through the services that interpret the chain, to the result a user sees.

What end-to-end products reveal

Each component can pass its own tests while the complete flow still fails at the boundaries. A node response, an indexer assumption, and a wallet operation can all look correct in isolation and still disagree when combined. Network upgrades make this especially visible, and there’s no better example than Ironwood, which requires consistent behavior across the chain and wallet stack; where every assumption must remain valid from block production through synchronization, transaction construction, and the user-facing result.

The same problem appears as zcashd reaches end of support. Matching methods on paper is not enough to prove that wallets can trust a replacement backend. Real clients must sync, recover, and spend. For me, product-level integration is one of the most reliable ways to get feedback on an upgrade, as it exercises every layer that contributes to a result, including complex flows that isolated requests and unit tests do not reach, since integration evidence often stays isolated.

Closed-source products can prove that a flow works, but their implementations are unavailable for others to study or reuse. Open-source products may use purpose-built stacks that fit their needs, and thus their tests exercise different boundaries than those of projects using the shared node, indexer, and wallet paths. Both approaches can be useful; the problem is that their findings do not automatically become tests and fixes in the repositories used by other teams.

What is missing is a common feedback loop: working products find integration failures, maintainers can reproduce them, and the corrections improve the repositories on which the wider ecosystem depends.

About this work

In my spare time, I’ve approached this by building complete product flows, then turning the failures they expose into tests and fixes in the repositories those products depend on; so take all of this as my personal views, not those of ZF. Nonetheless, being contracted as a DevOps/Platform Engineer for ZF for the past (almost 5 years), and my work across Zebra and other ecosystem repositories, has given me a direct view of where integration tests can help maintainers, and I am sharing this vision in a personal capacity.

Also, for years now, I’ve been building products and helping other teams build better developer experience and end-to-end flows, and those of you who follow me on X or on GitHub might be aware of that, as I share a lot of that work there.

What I built and what it uncovered

I built Zinder, Zally, Zpay, Zexplorer, and the Fauzec to exercise different combinations of the Zcash stack. The result is a set of working products that cross the full route from the network layer to the user interface.

Fauzec has to mine test funds, hold them in its wallet, and pay them to other wallets. That workflow crosses Zebra, Zinder, and Zally before a user receives funds. The same path must remain intact on the Ironwood-active public testnet: mining, shielding, wallet synchronization, and payout must be consistent across the node, indexer, and wallet.

Zexplorer connects Zebra and Zinder to a public interface that serves live mainnet and Ironwood-active public testnet data. It lets people inspect what the indexer reports without building their own client.

Zpay connects the Zally wallet path to checkout and limited, user-approved automated payments. Its public wallet holds its balance in Ironwood notes. A settled Zpay payment is publicly inspectable in Zexplorer with 2 Ironwood actions. In a fresh integration run, Zally also reached the public testnet tip via Zinder and maintained a non-empty Ironwood tree.

Together, these products exercise the faucet, explorer, wallet, checkout, and automated payment flows. They serve users, but they also test the route the next developer will have to follow. And this work has exposed bugs in wallet synchronization, transaction construction, rewinds, and shared tree storage. I reproduced those failures, turned them into tests, and contributed corrections upstream.

Examples include:

These fixes live in librustzcash and incrementalmerkletree, so future products inherit them. They are shared Zcash improvements, not private patches that only make my products work.

This follows the approach I have used across Zebra, Zallet, Zaino, librustzcash, and incrementalmerkletree: turn integration findings into upstream fixes and shared tests when the evidence supports them.

Extending existing Zcash work

The goal is not to create a parallel ecosystem or make every product use the same architecture; it is to give existing projects a tested route through shared components while they keep their own interface, identity, and relationship with users.

CipherScan, a ZCG-funded explorer, is a concrete example. I opened a draft adapter that preserves its HTTP and WebSocket interface while sourcing its data from Zinder. The adapter gives CipherScan a way to evaluate shared chain infrastructure without replacing its product. It also tests whether Zinder can meet the data needs of an existing grant.

Zcash Name Service is another strong integration. Zexplorer could resolve names, while Zpay could test payments to them outside the service’s own application.

The same approach can support OneKey and Hito with offline-signing cases.

BTCPayServer can reuse confirmation and reversal cases. QEDIT’s feature testnet can exercise new protocol features through public application flows.

Each project keeps its own product and architecture. The shared work adds another integration, reusable tests, and reproducible failures across repositories.

Making the path reusable

Zinder indexes the chain once and exposes a consistent view to explorers, wallets, and services. Products keep their own interfaces, and wallets keep their own keys and account state. Good architecture should make each boundary replaceable and testable without forcing products to share keys, account state, or a user interface. It also speaks the same wallet-service protocol as lightwalletd and compares its responses with the Go implementation in CI. This creates a compatibility path for existing clients.

The next external targets are a named release of ZODL’s Android wallet client and a direct Zallet backend (both of which have already been tested and are working, pre-Ironwood). The integration map shows which methods are already available and what still needs to be implemented or tested. The products already work end-to-end.

The next step is to make this route easier for another team to run. That means cleaner code, simpler deployment, clearer documentation, and CI that catches upstream compatibility breaks before they reach users. Stable releases, reproducible deployments, and clearer documentation can make the demonstrated paths easier for other teams to adopt and maintain.

Education projects such as ZecHub and Zcash Network School can also use the public flow as a practical lesson. Learners can request test funds, inspect a transaction, and complete a payment.

Success means another team can follow a documented route from node to product, reproduce a failure, contribute a fix, and keep the integration working without depending on me.

Where community input can help

  • Existing grant teams: Which shared capability would help you optimize work from your roadmap?
  • Developers: Where does the route from a local setup to a working product still break?
  • Maintainers: Which product-level tests would be most useful upstream?

Source code is available for Zinder, Zally, and Zpay. Zexplorer and Fauzec are public applications whose source code is not published.

I would especially like to hear from teams building wallets, explorers, payment tools, and developer infrastructure.

20 Likes

Strong agree on the boundary point, it matches what I keep running into: the components are individually solid, and the disagreements only show up once you actually chain them, which unit tests structurally can’t reach. Ironwood sharpens it, because a tool “supporting Ironwood” at its own surface isn’t the same as its outputs round-tripping cleanly through the next tool in the stack.

On which tests are most useful upstream: the highest-leverage one I’ve seen is an extension of the lightwalletd-vs-Go comparison you already run in CI, but at the artifact level rather than just RPC. Cross-implementation round-trip fixtures, pinned per version (“what tool A emits, tool B parses and validates”), turn a boundary break into a failing shared test instead of a support thread three weeks later. That class of failure is basically invisible until someone runs the whole route, which is your point exactly.

Thanks for building this :world_map:, super useful!!! :heart_suit: :shield: :zebra:

3 Likes

I agree with this. One thing I’ve noticed while building on Zcash is that many issues only become visible once you connect everything end-to-end. Individual components can work perfectly in isolation, but the real edge cases appear when you combine nodes, wallet synchronization, transaction construction, backend services, and the user-facing application. Those integration points end up surfacing bugs that unit tests alone don’t always catch. I think having more documented end-to-end paths would make onboarding new developers much easier.

3 Likes

Hi Gustavo. I agree, and this is exactly the kind of loop Zcash Network School and other local nodes can help make visible: real product flows, builders following the path, and then turning friction into docs, tests, issues, and fixes.

Would you be open to visiting us here at Network School for a first in-person round?

We can host a Zcash NS builder session, a workshop, or even a small structured series around this flow. If the idea makes sense to you, let’s discuss the details privately.

1 Like

this matches my experience almost exactly. I came into the ecosystem recently through the light client docs, and the individual repos are documented fine, it’s the seams that aren’t. the moment you want to know how zebrad, an indexer and a wallet SDK actually fit together you end up reading source and old forum threads. I’ve been fixing up the lightclient page in zcash-docs for exactly this reason, half of it described a stack that doesn’t exist anymore. a maintained end-to-end path like you describe would have saved me days. happy to help on the docs side of this if it goes somewhere.

The boundary point matches what I see on the privacy side, where each layer behaves correctly and the seams still leak what a user was doing. Would an end to end path pin down the metadata each hop can observe, or does that stay a separate map from the correctness one?

This resonates from the wallet side. I work on community and growth at Gem Wallet, and while reviewing our Zcash integration for NU6.2, we ran into a similar gap: understanding the implementation is one thing, but confidently verifying the complete transaction flow against a network upgrade is another.

A shared integration checklist or test harness covering transaction construction, signing, broadcasting, confirmation, consensus branch IDs, and backend compatibility would be very useful. It could also help wallet teams distinguish between code-level compatibility and functionality that has actually been tested end to end.

Would transparent wallet flows and node/backend upgrade compatibility be within the scope of what you’re proposing?