read.cash Log in
@pat

mainnet.cash - SLP wallet

Hey guys, in the previous article we have created our own in-browser bitcoin cash wallet using the mainnet.cash library. Today we will add the Simple Ledger Protocol (SLP) support to it. https://read.cash/@pat/mainnetcash-getting-started-a75b2fc6 SLP tokens in BCH are similar to ERC-20 tokens in Ethereum. These can be treated as valuable bits of information - very similar to Bitcoin Cash itself - floating on top of the blockchain, forming its second layer. If you are interested in what the SLP tokens are and how exactly do they work, consider visiting the https://simpleledger.cash and http://slp.dev. So let's start programming right away and duplicae the UI we have created for BCH and rename the HTML element ids and titles to have `slp` in their names, so we have no ambiguity. The result is this snippet, placed right after the BCH wallet's closing `div`: <div style="margin: 30px; flex: 50%;"> <h1>Simple ledger tokens</h1> <div>Wallet balance: <span id="slpBalance"></span></div> <div>Wallet balance USD: <span id="slpBalanceUSD"></span></div> <div>Deposit address: <span id="slpDepositAddr"></span></div> <div>Deposit QR: <img id="slpDepositQr"/></div> <div> <button type="button" id="getSlp">Get testnet slp tokens</button> </div> <div> Send to slp address <input id="slpSendAddr"></input> <input type="button" id="slpSend" value="Send SLP"></input> <input type="button" id="slpSendMax" value="Send All SLP Tokens"></input> </div> </div>

Now let's render the missing information in our SLP wallet by calling its SLP functions. For this we need to declare the `tokenId` of the token we will be working with. const tokenId = "132731d90ac4c88a79d55eae2ad92709b415de886329e958cf35fdd81ba34c15"; `tokenId` is a 64 character long string. In fact it is a transaction hash in which the token first *appeared* on the blockchain. The `tokenId = "1327..."` you see here is the `tokenId` of our `Mainnet coin` which we created for testing purposes beforehand. Working with SLP tokens requires precise knowledge of the token id. Knowing the token name `Mainnet coin` or its ticker `MNC` is not enough, since anyone can create a token with the same name and ticker and fool us about its identity. Now let’s duplicate the code in the `run()` function and start adapting it. First let's get the token balance of our wallet and update the UI: const slpBalance = await wallet.slp.getBalance(tokenId); document.querySelector('#slpBalance').innerText = `${slpBalance.value} ${slpBalance.ticker}`; document.querySelector('#slpBalanceUSD').innerText = `???`; This code looks familiar, doesn’t it? We access all the functions of an SLP wallet with a `wallet.slp` accessor. We have designed both wallet interfaces to be as close as it can get. Most notable difference is that you have to supply the `tokenId` everywhere in the function calls. Note, that we do not know the USD-MNC conversion rate, hence the `???` USD value. Watching the balance is similar to the BCH code: wallet.slp.watchBalance((slpBalance) => { document.querySelector('#slpBalance').innerText = `${slpBalance.value} ${slpBalance.ticker}`; document.querySelector('#slpBalanceUSD').innerText = `???`; }, tokenId); Let's now get the deposit address and deposit QR Code in the SLP format with the `slptest:` prefix (`simpleledger:` on the main network): const slpAddr = await wallet.slp.getDepositAddress(); document.querySelector('#slpDepositAddr').innerText = slpAddr; const slpQr = await wallet.slp.getDepositQr(); document.querySelector('#slpDepositQr').src = slpQr.src;

This is how the UI of our SLP wallet looks like now. Very similar to that of the BCH wallet. Now lets animate the last three buttons remaining: "Get testnet slp tokens", "Send SLP" and "Send All SLP Tokens". Getting the testnet `Mainnet coin` tokens from the faucet is very similar to BCH: document.querySelector('#getSlp').addEventListener("click", async () => { await wallet.getTestnetSlp(tokenId); }); Sending the tokens requires the knowledge of an SLP address of your counterparty and the `tokenId` which you want to send. // send some document.querySelector('#slpSend').addEventListener("click", async () => { const addr = document.querySelector('#slpSendAddr').value; await wallet.slp.send([{slpaddr: addr, value: 1, tokenId: tokenId}]); alert('Sent 1 slp to ' + addr); }); // send all document.querySelector('#slpSendMax').addEventListener("click", async () => { const addr = document.querySelector('#slpSendAddr').value; await wallet.slp.sendMax(addr); alert('Sent all slp funds to ' + addr); }); *Important notice:* getting the tokens from the faucet does not cost you anything. But the tokens will turn to be a dead weight if you don't have any spare BCH in your wallet. This marginal amount of BCH is required to pay the miners to move your tokens: compare to the Ethereum gas. So before trying to move the tokens, ensure you have claimed some BCH into your wallet too! Our resulting UI will look like this after claiming from both faucets and moving the tokens:

Note that our BCH balance is down by about 1000 sats. This is about ~4x larger than your usual transaction fee. Reason for that lays in fact that SLP transactions require a special non-monetary output which contains the information about the token movements. But don't be worried about all these complex matters - mainnet.cash library takes care of building these outputs and ensuring that your tokens will not get burned. This concludes our second tutorial article. Next time we will port our wallets to use the mainnet.cash REST server which will do the weightlifting for us, making our web page leaner.  Be sure to check out our **web site** and **library documentation**. You can ask any questions in our **telegram group**. The source code of this tutorial is available on github. https://mainnet.cash https://mainnet.cash/tutorial/ https://github.com/mainnet-cash/mainnet-tutorial/blob/master/3.tutorial.slp.html Cheers, pat for mainnet.cash team.

$1.08

8 comments

Log in to join in Reading is open to everyone. Replying needs an account.