mainnet.cash - SLP wallet

8 442
Avatar for pat
Written by
3 years ago

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.

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>
The resulting UI view.

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.

Cheers,

pat for mainnet.cash team.

34
$ 2.78
$ 1.70 from @TheRandomRewarder
$ 0.50 from @blockparty-sh
$ 0.27 from @Telesfor
+ 4
Avatar for pat
Written by
3 years ago

Comments

Today I tested sending and receiving SLP. It works well. I have many tokens on the memo wallet that I cannot send (e.g. BCH tokens or MIS tokens). I get an error message in memo. I tried to send BCH tokens with mainnet.cash. Something amazing happened. Instead of BCH tokens, WSB tokens were sent. Then I tried the same thing with MIS tokens. The same thing happened. WSB tokens were sent.

$ 1.10
3 years ago

Very interesting! Can you elaborate on it in an issue over here https://github.com/mainnet-cash/mainnet-js/issues ? Also, I have discovered an issue with nft tokens today, so try to avoid sending them with the lib.

$ 0.00
User's avatar pat
3 years ago

I will do it. I've noticed my BCH token and MIS token are burned.

$ 0.00
3 years ago

Nice thanks

$ 0.00
3 years ago

Sono informazioni molto importanti ma un po' complessa però

$ 0.00
3 years ago

Hey pat, you are giving really important info about mainnetcash. I think it's a bit complex to me but I'll check you posts when I need to use it ^^

$ 0.00
3 years ago

Sorry to hear it is complex to digest. I've tried to use no dependencies and use only basic things in this tutorial. How can we improve in your opinion?

$ 0.00
User's avatar pat
3 years ago

You explained perfectly dear but the whole proceess is a bit complex. People should spend some time to comprehend it :)

$ 0.00
3 years ago