Lisk is joining the Optimism Superchain ecosystem in 2024! Learn more about our planned migration to Ethereum, and what it means for our community, here

Building the Recurring Payments Project

Recurring Payments is a proof of concept made with the Lisk SDK. It shows a relatively simple technical solution utilizing custom transactions to build a deterministic contract between two parties (peer to peer). It allows you to set up a contract with anyone who creates an account (wallet) in the system. The accounts, the contract, all of its changes and all the activities are stored on the blockchain, which was specifically created for this PoC.

By Jurre Machielsen

05 Aug 2020

building-the-recurring-payments-project-OG@2x.png

In the Moosty team, we learn by doing. By building proof of concepts we learn about blockchain technology & the creation of network dynamics. We work together with communities (online & offline), knowledge institutes and organizations and have a strong link with the Lisk community, the LCU community & local businesses in Utrecht. Would you like to join this innovation journey with us? Let’s build a proof of concept together.

Project Introduction

Recurring Payments is a proof of concept made with the Lisk SDK. It shows a relatively simple technical solution utilizing custom transactions to build a deterministic contract between two parties (peer to peer). It allows you to set up a contract with anyone who creates an account (wallet) in the system. The accounts, the contract, all of its changes, and all the activities are stored on the blockchain, which was specifically created for this PoC.

The project has acquired a Lisk Builders grant. Hereafter we elaborate on the proof of concept.

contract-terminate.png

Use Case “Subsidy by governmental organisation”

Current situation

An organisation (A) applies for a subsidy from the government (B). This is currently paid in one amount for a period of 1 year. The receiving party must meet certain conditions during this period. If the recipient has not fulfilled the conditions at the end of the year, the grant must be fully or partially repaid.

Why should it work differently?

In the situation whereby party A has not complied with the conditions and the subsidy has to be repaid in whole or in part, you run into the problem that in most cases the entire amount has already been spent. This ensures that the subsidy provider (party B), is not assured of the amount to be recovered and that party A may run into financial problems.

How does the recurring payment work?

Party A draws up the contract with the terms of payment, including how often, when and the amount. Party B fills the safe with tokens to meet the contract conditions. Any period whereby party A is entitled to tokens from the contract, party A can execute a transaction to receive the tokens for that period. If party B wants to terminate the contract prematurely, the preset fee must be paid to party A, and party B will receive the remaining tokens from the safe. This can be compared to the premature termination of a contract.

Future

“In the future you are able to create a contract between yourself and your neighbor who happens to be a guitar teacher. You set up a contract for 1 year, whereby you pay him an agreed amount every month. You then deposit one months payment in advance, and if either party terminates the contract, the last month will be provided to the teacher. Once established the contract is immutable and it creates a transparent readable agreement between the two parties.”

A flexible service infrastructure

Today the tool uses only a handful of custom transactions. With these six custom transactions we have the potential to build a powerful blockchain application that creates a flexible contracting solution between two parties. It gives you the possibility to create the following:

  • A monthly payout mechanism.
  • Provide a subsidy whereby the money is automatically unlocked after 3 (or more) months, unless someone terminates the contract.
  • A subscription where you pay the full amount upfront (to receive a discount).
  • A service contract where you pay 2 periods in advance.
  • Set aside pocket money for your children.
  • Schedule monthly donations up to a maximum amount.

There will be a multitude of possibilities when we extend the functionality of these transactions, or when new custom transactions are added and we incorporate 10 or maybe 20 different transactions.

For example: Create a crowdfund with a (maximum) monthly payout to the crowdfunder.

Let us know if you have even better ideas!

Technical details

This section contains an introduction to the technical details and provides an overview of the different frameworks used, the custom transactions created, and finally our experience from working with the Lisk SDK.

Components of the PoC

  • Back-end: Working custom transactions that can run on a blockchain.
  • An extended HTTP API connecting the back & front-end.
  • Front-end: A ReactJS front-end wallet to manage contracts (interact with the transactions).

Custom Transactions

“Transactions are an essential part of blockchain applications that are created using the Lisk SDK, as they define the set of actions that can be performed by users in the network. Each transaction belongs to a specific transaction type that is registered in the network.” Lisk SDK Documentation.

This proof of concept uses six different custom transactions. Different transactions can interact with contract wallets as listed below:

  • Create - making the contract.
  • Review/accept - review & validate the contract.
  • Fund contract - deposit tokens in the contract.
  • Withdraw - get tokens from the contract.
  • Terminate - Premature termination of contract.
  • Faucet transaction - provides the wallet with tokens and username registration

 

overview-page.png

Note: transactions will work with units of minutes in this proof of concept to simulate contracts faster.

See the Open Lisk Transaction Type Registration repositoryfor a list with all registered Lisk transaction types. Everyone can make a pull request to add new or update existing registrations, and also reuse the registered custom transactions in order to quickly set up your own blockchain app.

Contract

A contract is made with different rules that must be adhered to as shown below:

  • Unit: time unit [daily, weekly, monthly, yearly].
  • Unit price: how many tokens each unit can retrieve from the safe.
  • Prepaid units: how many units * price must be in the safe.
  • Start: when the contract starts.
  • Total units: how many units do the contract contain.
  • Termination fee: how much of a fee is paid with the premature cancellation of the contract.
  • Recipient: what address can each unit take time tokens from the safe (lot A).
  • Contractee: what address may the safe fill (lot B).
  • Description: description contract.
  • Name: name of the contract.

How does it work?

A contract can be made by either the future sender or the recipient of a contract. This contract can be approved or modified by the other party through the validation transaction. If the contract is modified, the first party must approve or reject this modification. This process can be repeated until both parties are in agreement. A vault can be filled by the sender (party B), with a custom fund transaction which uses complete payment amounts and activates the contract.

 

contract-awaitingreview02.png

The receiving party (A) can retrieve tokens from the vault with a transaction if the contract allows it at that time. If prepaid conditions are not met, then the contract will not be activated. Both parties can prematurely terminate the contract with a termination transaction in which the remaining amount is returned to party (B), after a deduction of the short fee, and subsequently, the short fee is then paid to party A.

 

contract-awaitingreview03.png

SDK 4.0

This PoC uses the Lisk SDK 4.0. This provides Dynamic Fees and Chain State. The chain state store is used to determine the time of the transaction and can determine from the contract state how many tokens are unlockable. In this version of the SDK the timestamp is removed from the base transaction and a nonce is introduced. Due to the incremental nature of the nonce, the front-end retrieves the account nonce from the blockchain every time, just before a transaction is signed.

File name
1
2### Dynamic Fees solution
3
4Dynamic fees work like a charm. Due to missing documentation (as we started using v4 too early), it took some time to work out how to calculate them. We solved it in the following manner described below:
html const tx = new FundContractTransaction({ nonce: nonce.toString(), senderPublicKey: publicKey, asset: { ...data } }); tx.fee = (tx.minFee + BigInt(65000)).toString(); tx.sign(config.networkIdentifier, passphrase); ```

BigInt

For the front-end we had a problem with BigInt (issue), because BigInt uses a Buffer library for js in the browser which has not yet completed the integration of "buffer.readBigUint64BE()". This function is used in the Lisk SDK and is needed for signing transactions. The pull request for this function is in the pipeline but has not yet been accepted at the time of writing. We fixed it by forking the buffer repository and merging it with the pull request to make it work for now.

HTTP API

The default Lisk HTTP API has been extended with an extra API module to make it possible to search for partial usernames, contract specific asset fields and transaction specific assets fields. For example, every contract has transactions belonging to itself but the account is never the sender of any transactions. To collect all transactions belonging to a contract, the API will receive the transactions from the transaction entity by adding a "asset_contains" filter to the Transaction entity. This makes it possible to search on ".asset.contractPublicKey" === "contract.publicKey".

Front-end

The creation of custom transactions in the back-end is relatively easy when you start getting the hang of it. The most time consuming element is the front-end, depending on the UI requirements, and connecting the two together. Gathering data from the blockchain can be optimised further, however it is outside the scope of this proof of concept.

The undoAsset() method

In addition, the UndoAsset() method in a custom transaction can be difficult to create with static nominal data. We are looking forward to the new solution to create custom transactions without the UndoAsset() method, which has already been planned in a later version of the SDK. Solving this will ensure the review transaction sends a lot less data, and hence uses less network resources, which in turn results in lower dynamic fees.

Resources

If you feel inspired and want to build your own proof of concept blockchain application, check out the Lisk Grant program. More information about the program and the application procedure can be found on the Lisk webpage for the Lisk Grant Program.

Disclaimer: This blog post was written by our community member, Jurre (Lisk.chat username: Jurre | Moosty) as part of his participation in the Lisk Builders program.