Saving Shielded Transactions History

Building a UI wallet for a private cryptocurrency like Zcash has several interesting UI tradeoffs.

Sending shielded transactions in Zcash is awesome, but there’s a lot to trip over for new users. For starters, the zcash node, doesn’t save outgoing shielded transactions, so there’s no way for a UI to get these from the node and display them in a “history” or “transactions you made” tab.

While not storing private transactions is probably the right call for a zcash node, it comes as a nasty surprise to users of the UI wallet.

A UI needs to build trust with users before they’re fully comfortable using it. For a private and secure cryptocurrency like Zcash, this is doubly true.

This trust is broken when you can’t see a transaction that you just sent. It frustrates users and creates more questions. Did the transaction actually go or did it fail? How much was sent?

To make sure users have a trustful experience with zcash-qt-wallet, I decided to store shielded transactions, at least those sent through the UI, locally. These transactions are then added to the information from the zcash node to show a full history of transactions, for both transparent and shielded addresses.

This was an interesting challenge, since the mental model used by the zcash node is different from what’s in the users head, and making everything consistent and add up is a fun UX challenge.

Incoming z-Address transactions

The way to get incoming z-Address transactions is to look up z_listreceivedbyaddress, which gives you a transaction id, and then do a second lookup to gettransaction to get the details about the transaction, like the timestamp, number of confirmations etc…

The zcash node lists “change” from a transaction as a separate incoming transaction for the z-Address. Now this is technically accurate, since the “change” from a transaction is sent as a new note, but users are surprised when they see their own money come back to them as a new incoming transaction. This is doubly confusing because change from a transparent Address doesn’t show up separately.

So, I decided to suppress these incoming “change” transactions from z-Addresses by ignoring them in the transactions tab.

This ensures that the numbers add up on the transactions tab. That is, the sum of all outgoing and incoming amounts should equal your current balance.

I think this is a good principle to have for a UI. When users can see that everything is consistent and adds up, they know they can trust the UI.

Outgoing z-Address transactions

The UI can save all outgoing z-Address transactions locally, and load them into the transactions tab.

This list might be incomplete, since the UI has no way of finding out if you sent outgoing shielded transactions from elsewhere, but I decided to make this tradeoff anyway.

If the user uses the command line to send an outgoing shielded transaction, they will likely not be surprised when it doesn’t show up in the UI. However, the corollary is bad UX — If they use the UI to send an outgoing shielded transaction, but it doesn’t show up in the same UI, that’s bad and it breaks user trust.

User Control & Privacy

Some users might want to opt out for privacy reasons, so there’s a checkbox in the options tab for those that want to opt-out and even a button to delete history.

There’s another choice here: Even if we don’t store outgoing transactions, we can still show incoming z-Address transactions in the UI, since zcashd can report them. But should we?

Showing only incoming shielded transactions will create an inconsistent UI experience, though. You’ll see incoming transactions, but none of the outgoing ones, so the amounts on the tab won’t add up to the balance.

This again breaks UI trust The numbers should always add up.

Therefore, I decided to call the opt-out option “Show shielded transactions” instead of just “Show outgoing shielded transactions”. And when users opt out, we don’t show neither outgoing nor incoming transactions in the transactions tab.

zcash-qt-wallet is a UI frontend for zcashd which allows you to easily send and receive private, shielded transactions using Zcash. You can learn more here: