zknifty is a working example of non-fungible tokens (NFTs) based on zk-SNARK proofs. However, it was not designed for privacy as its goal is to "compress" several transactions into one proof (i.e. it minimizes the stored data on the smart contract). The basic idea is that the smart contract stores only the root of a Merkle tree of which any change fulfill the following requirements:
- The actual owner of the token to be transferred signed a message
- This message is composed of the token ID and the receiver address
- The signature is valid
- The token transfer is reflected in the new merkle tree
The preimage of the leaves of this tree contain the owner's public key and the identifier of NFTs. It does provide some privacy since only the root the tree is stored on the contract and it is not possible to gain knowledge from these proofs.
There are some caveats though:
- As this project was not designed for privacy, leaves do not contain a nounce and hence can be guessed by brute-force; i.e. h(token ID || receiver address) with a known set of token ID and addresses.
- Since you are asking this question for Ethereum, an Ethereum transaction always contain the sender address which might be an issue.
Disclaimer: I am not the author of zknifty