
My First Time Using The Lisk.io Blockchain
The other week I had the privilege of attending a Lisk workshop for developers who wanted to try out the Lisk Blockchain. Despite all the hype about the blockchain, there are still many barriers to its mainstream adoption like the need for developers to learn multiple coding languages including lesser known ones like ‘Solidity’ (for Ethereum). Lisk aims to remove these complications by creating simple functions in JavaScript that developers can use to build on the Lisk Blockchain. Lisk also aims to solve an even bigger problem with the Blockchain, but we’ll get to that later.
You can learn more about Lisk’s story here.
The aim of this workshop was to create a ‘Custom Transaction’ (i.e. a blockchain) that can be tailored to a variety of use cases. The specific scenario we’re attempting to address in this workshop is as follows:
Bob is looking for a new logo for his website and decides to consult a freelance designer. While looking for a good designer, he comes across Alice who offers some spectacular designs in her portfolio. Bob is so excited he decides to immediately hire Alice.
A few days go by, and Alice returns the promised logo together with an invoice. However, Bob is a big fan of blockchain technology as it can help ease the settlement process when parties disagree about the agreed price, product, or even shipping terms. Bob believes that the blockchain can help with recording all of this information so that no disputes occur and the room for human error is minimised. The blockchain acts as proof of the transaction.
For the reasons above, Bob asks Alice to create an invoice via a Lisk custom transaction (InvoiceTransaction). Bob then creates another custom transaction to pay Alice (PaymentTransaction).
As explained above Alice will create a custom JavaScript class called InvoiceTransaction which will contain the client’s name, amount owed and a description of the services that have been provided. In return Bob will create a custom class called PaymentTransaction which will take funds from his account and send them to Alice.
In order to create the two custom JavaScript classes above we will be extending existing classes created by Lisk, namely TransferTransaction and BaseTransaction so that we can have access to Lisk’s functions.
Folder Structure

Our root folder for this exercise will be the workshop folder. As visible from the screenshot, the transactions folder is a child of the workshop folder. It contains a index.js file which exports the InvoiceTransaction and PaymentTransaction for use by other JavaScript classes. The code within looks like this:
const InvoiceTransaction = require('./invoice_transaction');const PaymentTransaction = require('./payment_transaction');module.exports = {InvoiceTransaction,PaymentTransaction};
The parent workshop folder contains another index.js JavaScript file that imports the two custom classes from the transactions folder and registers them to the blockchain. You can see the contents of that file below:
const { Application, genesisBlockDevnet, configDevnet } = require('lisk-sdk');const { InvoiceTransaction } = require('./transactions/index');const { PaymentTransaction } = require('./transactions/index');const app = new Application(genesisBlockDevnet, configDevnet);app.registerTransaction(InvoiceTransaction);app.registerTransaction(PaymentTransaction);
The last two lines of the code register the new custom transactions to the Lisk blockchain. Now that we understand how custom transactions are implemented, we can begin writing the details of the transaction.
InvoiceTransaction (Alice’s Custom Transaction)
As mentioned above Alice wants a InvoiceTransaction class. To do this she needs the following fields:
- A unique identifier for her custom transaction to register it on the Lisk blockchain [variable 1]
- Amount owed for her services [variable 2]
- A description of the services provided [variable 3]
- Another identifier to differentiate the invoice sent to Bob from other invoices that she has sent[variable 4]
- A variable to keep count of the number of invoices she has sent to customers[variable 5]
Alice is going to identify her custom transaction (variable 1) as number 13 on the blockchain. Lisk will charge her 100m beddows (variable 2 and a unit of measure named after Lisk founder Oliver Beddows) to register her invoice on the Lisk blockchain. In case you were wondering 100m beddows gives 1 LSK which is worth ~$0.80 at the time of writing. You can find the latest LSK/USD rate here.
Alice will call variable 3 ‘invoice for logo work’, variable 4 is an array of ids’ that have been sent called invoicesSent and variable 5 is a number called invoiceCount. She then writes these functions into the InvoiceTransaction class. You can see how it’s done here.
In the codebase Alice defines the characteristics of the ‘custom transaction’, but the more interesting functions are validateAsset() and applyAsset(). The function validateAsset() checks that the client, the amount requested and the description variables exist and are not strings. The applyAsset() function accesses the store of locally cached data (which includes Alice’s account details) and checks that the custom fields of invoiceCount and invoicesSent exist. If they don’t it creates them and adds the required information. These function are interesting because they are predefined by Lisk, and allow a developer to access and customise them.
Finally the undoAsset() function is used to remove all of the ‘Asset’ variables (variables unique to this type of transaction e.g. Invoice) created by the applyAsset() function. It is to be used when the user forks (copies) the custom transaction (to re-use it) and wants to clear the information held. For instance Alice could make a new custom transaction to confirm that her work has been sent to the client. To do this she could copy the existing custom transaction used for invoices and use the undoAsset() function to remove the ‘Asset’ variables invoiceCount and invoicesSent. She would then create new variables like a boolean field called workSent after writing a new version of applyAsset() to verify that her work has been sent.
You can get a more detailed explanation of what’s going on under the hood here.
To begin broadcasting the invoice and add a block to the chain Alice can run the following command node index.js | npx bunyan -o short. This simply runs the index.js file (i.e starts the node) located in the workshop folder and sends the information output to a log formatting tool called bunyan that prints it in a readable format in the console.
To verify that the new custom transaction is working Alice can paste the following code into her terminal.
curl -XPOST -H "Content-type: application/json" -d '{
"id": "6068542855269194380",
"amount": "0",
"type": 13,
"timestamp": 106087382,
"senderPublicKey": "c094ebee7ec0c50ebee32918655e089f6e1a604b83bcaa760293c61e0f18ab6f",
"senderId": "16313739661670634666L",
"recipientId": "8273455169423958419L",
"fee": "100000000",
"signature": "4855b3b65484b94e6653601dfcafe1205a77fd16431c9e034460015ae9c09e1bd81be7877c9b9cca68b63979a3483589f79b2619093f3266e46515f16382cd02",
"signatures": [],
"asset":
{ "client": "Michiel GmbH",
"requestedAmount": "1050000000",
"description": "invoice for logo work" }
}' http://localhost:4000/api/transactionsThis will send the content in the form of an API to the local server http://localhost:4000 where this transaction is validated and then written to the blockchain, subject to the rules Alice wrote in the function above (using validateAsset() and applyAsset()). You can read more about the process here.
PaymentTransaction (Bob’s Custom Transaction)
Bob will be following the same steps as Alice in creating a new PaymentTransaction. He will need:
- A unique identifier for his custom transaction [variable 1]
- The sender’s Id [variable 2]
- The recipient’s Id [variable 3]
- A unique identifier of the invoice he needs to pay (e.g. the Id of the invoice Alice sent Bob) [variable 4]
Bob will extend the TransferTransaction class instead of the BaseTransaction class so that he can access a different set of functions. To understand when to use which Lisk class, you can check this guide.
Bob will be using 14 for variable 1 and will obtain the remaining variables(2, 3 & 4) from the store which retrieves the data from the database.
In Bob’s custom transaction his applyAsset() function is slightly different to Alice’s and simply checks that the amount being paid is equal to the amount stated on the invoice. It also checks that the invoice has been sent to the right person.
Bob’s transactions can be registered on the blockchain by sending it through via a test API. The code below sets up Bob’s Lisk account with funds.
Note: This is done with a type 0 transaction type.
curl -XPOST -H "Content-type: application/json" -d '{
"amount": "10000000000",
"recipientId": "8273455169423958419L",
"senderPublicKey": "c094ebee7ec0c50ebee32918655e089f6e1a604b83bcaa760293c61e0f18ab6f",
"timestamp": 106429639,
"type": 0,
"fee": "10000000",
"asset": {
},
"senderId": "16313739661670634666L",
"signature": "bd2cc2c0a653aa2ea25b5034c885a53a5f44779d527f1f0e476b5a5fa08deb86d4dd7fc86133f8fba75fcc9f8fae92c11bf1bf6df55efc5f50ca8dba675f7202",
"id": "4232693658353776133"
}' http://localhost:4000/api/transactionsThe next API will transfer funds out of Bob’s account and into Alice’s account using his newly created type 14 transaction type.
curl -XPOST -H "Content-type: application/json" -d '{
"id": "14610813406835243898",
"amount": "1100000000",
"type": 14,
"timestamp": 106416998,
"senderPublicKey":
"9d3058175acab969f41ad9b86f7a2926c74258670fe56b37c429c01fca9f2f0f",
"senderId": "8273455169423958419L",
"recipientId": "16313739661670634666L",
"fee": "10000000",
"signature":
"a9cfd197227737aaa05d2292ff6a278e6ab81e412b9c17363d0e4a942f8f28c78407f58f46ef56f8fb755de5eec1775a0214d2b789163cf75036f6ee655bd104",
"signatures": [],
"asset": { "data": "6068542855269194380" }
}' http://localhost:4000/api/transactionsAs a final check you can type curl http://localhost:4000/api/accounts?address=16313739661670634666L into the browser to check that Alice has been paid.
You can see the complete technical tutorial here.
The Bigger Picture
The biggest obstacle for mainstream adoption of the blockchain is scalability. For comparison Visa processes ~1,700 transactions per second, whilst Ethereum can handle 15 and Bitcoin processes about 4. Although there have been some potential workarounds like The Lightning Network, sharding and plasma, the blockchain still has a long way to go. This is due to some of the features of the blockchain that limit the ease with which new blocks can be added to the chain.
Lisk seeks to overcome this challenge by introducing sidechains (the custom transaction above is a sidechain). A sidechain is a separate blockchain that is joined to the main Lisk blockchain via a node. Each sidechain can launch its own ICO (using its own currency) or use LSK tokens as payment for adding new blocks to the sidechain. This means that even if a sidechain goes down, the blockchain can continue to operate and grow.

The sidechain can also have it’s own delegates that process and approve new blocks into it. That means that new blocks added to the sidechain won’t slow down the main blockchain and vice versa.
Right now, Lisk is working on developing sidechains. The two ‘Custom Transactions’ which Alice and Bob built above are going to be developed into sidechains (right now they’re marooned blockchains) when Lisk releases their completed sidechain SDK.
Final Thoughts
It was a pleasure to take part at the workshop at Lisk and it shows what community driven events financed by an ICO can achieve. In addition, Lisk has put a great deal of effort into educating the developer community, and I definitely wouldn’t have been able to write this article without all of the resources and knowledge that they have shared. I’m looking forward to the full release of their sidechain SDK!