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.
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.
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.
“In the future you are able to create a contract between yourself and your neighbour 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:
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!
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
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:
Note: transactions will work with units of minutes in this proof of concept to simulate contracts faster.
See the Open Lisk Transaction Type Registration repository for 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:
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.
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.
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.
// slotTypes = [minutes, hours, days, months] in seconds
export const getPastSlots = (
start,
now,
type,
length,
unit
) => {
const slot = slotTypes[type] * length;
return Math.floor((now - start) / slot) - unit;
}
const unitsAvailable = getPastSlots(
contract.asset.start,
store.chain.lastBlockHeader.timestamp,
contract.asset.unit.type,
contract.asset.unit.typeAmount,
contract.asset.payments
);
Dynamic Fees solution
Dynamic 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:
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.If you feel inspired and want to build your own proof of concept blockchain application, check out the Lisk Builders program. More information about the program and the application procedure can be found on the Lisk webpage for the Lisk Builders 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.