Granted: Full lightwallet functionality for .NET

I’m delighted to (once again) be the recipient of a Zcash Community minor grant. I’ll be adding full lightwallet functionality for .NET to our Nerdbank.Zcash project that was started from the first grant.

Development is taking place at the following GitHub repo:
nerdcash/Nerdbank.Cryptocurrencies: .NET libraries for processing Zcash and other cryptocurrencies. (

A good deal of functionality beyond the initial grant is already in place. We have key derivation, a few BIPs and ZIPs implemented, and .NET APIs that expose some of the functionality required for .NET to act as a lightwallet client.

In the next month, I hope to implement and stabilize most functionality except for transaction download and creation – the functionality that actually requires interacting with the blockchain. I have prototypes of a very limited set of lightwallet sync functionality, but there’s lots more work to do. I’m consuming ZingoLib (from the Zingo team, also funded by a Community Grant) for some of this functionality, and that team is working through some bugs and features that will be important for this project to consume, so scheduling this work for more than a month out should help our requirements and their features align.


As an update, here is the new functionality for the past month:

  1. Added a function to easily parse a variety of key encodings or seed phrase into a ZIP-32 account.
    Add `ZcashAccount.TryImportAccount` by AArnott · Pull Request #107 · nerdcash/Nerdbank.Cryptocurrencies · GitHub
  2. Refactor some keys:
    Split sapling diversifier from the IVK class by AArnott · Pull Request #109 · nerdcash/Nerdbank.Cryptocurrencies · GitHub
  3. Ensure generated seed phrases have a minimum of 24 words:
    Add requirements about seed length, and document entropy requirements by AArnott · Pull Request #112 · nerdcash/Nerdbank.Cryptocurrencies · GitHub
    Improve enforcement of 256-bit entropy for ZIP-32 by AArnott · Pull Request #113 · nerdcash/Nerdbank.Cryptocurrencies · GitHub
  4. Encodable transparent private keys by AArnott · Pull Request #120 · nerdcash/Nerdbank.Cryptocurrencies · GitHub
  5. Add Yahoo! Finance as a provider of historical prices by AArnott · Pull Request #121 · nerdcash/Nerdbank.Cryptocurrencies · GitHub
  6. Added API so users can tell whether a pair of Zcash addresses refer to the same recipient, assuming the diversification index or transparent address index is the same:
    Add `ZcashAddress.IsMatch` API by AArnott · Pull Request #127 · nerdcash/Nerdbank.Cryptocurrencies · GitHub

In the next month, as expected I’ll be working on sync functionality (download and sending transactions) and balances. I hope to provide APIs by which a wallet app can convey very user-friendly concept balances (i.e. not the same ones I tend to see in wallets today). Here’s an example:

True auto-shielding functionality is also on the backlog, and I hope to get it done in the next 30 days as part of the sync work.

Finally, and this is something of a stretch goal, I hope to include shielded pool balancing functionality so that the wallet app (or user) can decide what proportion of their funds to keep in sapling vs. orchard. When each shielded pool carries a balance, payments are less likely to have to cross the turnstile, revealing the amount (or at least a clue about the amount) in a transaction.


Downloading and sending transactions is better now, but bugs in zingolib cause importing of older accounts to present bad balances, show bizarre amounts on the transactions, etc. Debugging their code to help author fixes is a bit overwhelming (for me) since I’m still ramping up.
As a possible alternative I’ve been looking at consuming the zcash_client_backend and zcash_client_sqlite crates instead. There is a lot of work involved in this switch, and I’m not sure whether it will be successful. So far though, I have re-implemented account sync, and it implements a faster sync algorithm so I think it’ll be a good long-term move. It does mean re-implementing some of the functionality that I already had through zingolib, so feature progress will appear to stall for a time (not sure how long yet).

Getting familiar with these lower-level crates also opens up possibilities for more use cases, which for a .NET library I think will be very interesting. I hope to allow for directly importing of various key types (so, not only just 1 seed phrase) for example).

Before this rust dependency reset, in the last 30 days some good stuff got done:

Innovative ideas implemented

  1. Implemented the actual balance calculations necessary to present the screen shown in my last post:
    Add rust calculation of meaningful user balances by AArnott · Pull Request #150 · nerdcash/Nerdbank.Cryptocurrencies · GitHub
  2. Give users better birthday heights for their accounts for faster sync times when importing into a new wallet:
    Add means to retrieve more birthday height values by AArnott · Pull Request #176 · nerdcash/Nerdbank.Cryptocurrencies · GitHub

Feature or API enhancements

  1. Add ImportAccount command to CLI by AArnott · Pull Request #166 · nerdcash/Nerdbank.Cryptocurrencies · GitHub
  2. TradingPair and historical data improvements by AArnott · Pull Request #167 · nerdcash/Nerdbank.Cryptocurrencies · GitHub

Not terribly surprised. I remember looking @ zingo-pc/src/rpc/rpc.ts at dev · zingolabs/zingo-pc · GitHub and aside from being 1200+ LOC,

and that’s just the electron code base.

At least the mobile repo has e2e tests… :smile:

I have a branch where Nerdbank.Zcash is backed directly by the lower-level crates zcash_client_backend and zcash_client_sqlite. This version scans blocks much more quickly than the zingolib branch, and there is room to about double that speed as well. But these crates do not (yet) fully support orchard, which zingolib already supports. Zingolib does not yet have the sync bugs worked out, and the lower-level crates don’t support transparent pool transactions very well either.

So I’m in something of a holding pattern now, waiting for the dependencies in either branch to mature to the point where they are both full featured and can be reliably used. In the meantime, I’m studying the lower-level crates more and authoring a few small PRs to them. My hope is to help move the work along wherever I can.

I also made a few small improvements on the .NET side, namely:


I’ve had a most effective time learning the zcash rust crates and even contributing to them. You can see the evolution of my contributions from docs and small fixes to significant refactorings such as Define our own AccountId by AArnott · Pull Request #1175 · zcash/librustzcash ( which paves the way to supporting multiple accounts that are not all from the same HD seed, as well as imported accounts (for which no seed is known).

I also completed my migration from ZingoLib to the librustzcash crates. We lost mempool transactions and orchard support in the transition, but picked up ZIP-317 fee support. librustzcash is expected to deliver orchard support very soon, and I’ll pick that up right away when it’s available. Mempool transactions shouldn’t be hard to add support for as well.

Following are noteworthy changes made since my last post:

I copied the grant proposal deliverables into a GitHub issue to track remaining work:
Funded Zcash proposal: Complete full lightwallet functionality for .NET · Issue #229 · nerdcash/Nerdbank.Cryptocurrencies (
As you can see from that list, the work is virtually complete.
Mempool support was specifically mentioned in the grant proposal under the assumption that the rust crate the .NET library depends on would support it. Since the librustzcash crates don’t yet support it, I’m proposing we drop it from the spec of the .NET library, under the expectation that it will be filled in when the rust crate offers it (which I might contribute myself).


I have completed the work for the grant.

Release v0.2.68-beta · nerdcash/Nerdbank.Cryptocurrencies (
NuGet Gallery | Nerdbank.Zcash 0.2.68-beta

Watch the demo, which walks you through creating a cross-platform C# application that functions as a Zcash wallet in under 8 minutes:
Zcash .NET library demo video


Fantastic work, really liked your video! Will you post this demo and code into places like The Code Project? I want to see if I can get this working in Linux as well. :clap:

1 Like

I’m delighted that you want to try building on this! Yes, I’ll write something up and share the code. I’ll post a link here when ready.


Here is the source code. Watch my blog for a post about this soon.

It already works on linux, because Avalonia is a cross-platform GUI framework. This is running the build I produced with Visual Studio on Windows, running under WSL:

It builds fine on linux as well.


Will check out, thanks again! :student: :zebra: