Hey everyone!

Little post I have decided to write up today about SLP integration into bitcoincashj. For those that do not know, bitcoincashj is a Java library for Bitcoin Cash development. I am currently the sole maintainer of the library after the former maintainer stopped development and switched to bitcoinsvj or something.

This will be somewhat of a technical post. I will be going over the current status of SLP integration into the library, and what I did to implement it quite easily.

For starters, let us look at the GitHub repo of my fork of bitcoincashj: https://github.com/pokkst/bitcoincashj/tree/slp

This is where I have been working on SLP integration.

To make things much simpler for development I opted to use bitcoincashj's internal UTXO management system rather than write my own for managing SLP UTXOs. By default, bitcoincashj does spend dust UTXOs when it can. This is both an issue in regards to SLP tokens, and privacy with dusting attacks. So I made a change in bitcoincashj to completely ignore dust outputs when spending.

Next I had to write the system for the actual wallet portion. Since SLP tokens are meant to be on derivation path m/44'/245'/0' I had to make some changes to bitcoincashj to allow for custom derivation paths to be set during runtime. Prior to this, derivation paths were hardcoded into bitcoincashj. I then copied the normal WalletAppKit in bitcoincashj (https://github.com/pokkst/bitcoincashj/blob/slp/core/src/main/java/org/bitcoinj/kits/WalletAppKit.java) and made my own version called SlpAppKit that uses the recommended derivation path (https://github.com/pokkst/bitcoincashj/blob/slp/core/src/main/java/org/bitcoinj/kits/SlpAppKit.java).

Now I have a custom wallet kit loading with the correct derivation path (and therefore correct addresses), but the wallet kit has no idea what an "SLP token" is! To fix this, I made a method in SlpAppKit called recalculateSlpUtxos (https://github.com/pokkst/bitcoincashj/blob/slp/core/src/main/java/org/bitcoinj/kits/SlpAppKit.java#L455). This method loops through the wallets UTXOs (as managed by bitcoincashj itself) looking for UTXOs that belong to an SLP transaction. When a UTXO matches the specified criteria, it then calculates the actual amount sent as specified in the OP_RETURN in its raw format. We then grab the token ID from the OP_RETURN.

To find out if we know the token with the token ID we just grabbed, we have a JSON file with token details. This includes: ticker, decimals, and tokenId. We loop through the stored SLP tokens until we find our specified tokenId, and then use the decimals data to properly format our raw amount. If the tokenId is not found in the database, then we grab the token details from SLPDB and save it to the database (https://github.com/pokkst/bitcoincashj/blob/slp/core/src/main/java/org/bitcoinj/kits/SlpAppKit.java#L489). This caches the token details so we do not waste time contacting SLPDB each time, and/or overload SLPDB with requests.

In recalculateSlpUtxos, we then manage the balances of each token in our wallet. Rather than managing it by adding and subtracting, we only add. To do this, we simply clear the tokens array when we recalculate.

Great! Now the wallet knows what SLP tokens are, knows the balance of each, but it has no idea what to do with them! This is where createSlpTransaction comes in. This is almost a direct port from the Bitcoin.com SLP SDK. The difference being is that this one is written in Java by me, versus Kotlin by Bitcoin.com (https://github.com/pokkst/bitcoincashj/blob/slp/core/src/main/java/org/bitcoinj/kits/SlpAppKit.java#L319). Here we determine what token we are sending, then we check our tokens database to find if we have that token, and if we do we determine if we have enough tokens to send. We then determine which UTXOs to spend, then craft the OP_RETURN and specified outputs for the tokens to be sent to. Then in broadcastSlpTransaction, we take the tx returned to us in createSlpTransaction and broadcast it to our wallet's PeerGroup. Directly sent to the Bitcoin Cash network!

The end result is a fully-featured SPV Bitcoin Cash wallet with native SLP integration! I hope you have enjoyed reading this as much as I have enjoyed developing this. If you have any questions, feel free to ping me on Telegram, Twitter, or wherever. :)