Developer Christophe Verdot talks about the online course ' Mastering Web 3.0 with Waves ', which he recently passed.
Tell us a little about yourself. What interested you in this course?
I have been involved in web development for about 15 years, mainly as a freelancer.
While developing a long-term register web application for developing countries commissioned by one banking group, I was faced with the task of integrating blockchain certification into it. At that time, I did not know much about blockchain certification, although I was already interested in crypto technologies - mainly as an investor.
As a result, this function was not implemented, but, thinking that organizations and banks were interested in such a solution for their applications, I began to study the issue and soon launched the
Signature Chain project.
I developed its beta version, which is already available on the main network. There was no [Waves programming language] Ride at the time, and I did everything in the simplest way using translation transactions with embedded JSON. But the main goal was to add more advanced functionality after the launch of Ride. And this is the main reason I joined the course: the next stage in the development of the project involved the creation of a decentralized application (dApp).
Which aspects of the course seemed most simple to you and which were the most difficult?
The simplest thing was that we had enough time for all tasks. The meaning of the course is to learn something, and not compete with each other. The explanations were very accessible, and the illustrations were simple but comprehensive. It helped to visualize and understand different topics.
When completing assignments, we were pushed to think independently and sometimes to study something on our own. This is the best way to learn something and understand the ideas discussed in the classroom.
Several times I did not fully understand the theoretical part until I started writing code while completing the task. We were not allowed to do 'copy / paste', all the code needed to be written by ourselves, and this also helped to better understand everything.
The most difficult part was that the questions in the assignment with several answers were not always clear. My English is not perfect, and the questions were written by a person who is not a native speaker, so sometimes there was a misunderstanding.
Perhaps the oracle and NFT part of the course could be more detailed. But, in any case, the main objective of the course is to interest developers. Then, in order to fully understand all its aspects, it will, of course, be necessary to spend some time experimenting and practicing.
Tell us more about the solution that you worked on throughout the course - 'Coupon Bazaar'? Can I also see code examples?
Yes, we worked on 'Coupon Bazaar', this is a marketplace where people sell and buy coupons giving them the right to buy goods and services at a lower price. Each coupon is represented by a digital asset, which involves a special discount from the supplier.
It was necessary to develop several application components. Firstly, it was necessary to create a system for registering suppliers and managing coupons. Then we needed a verification function and the ability to search for coupons by users.
During the course, we also added several new features, including a voting system and a feature that allows us to verify and blacklist suppliers.
First, we examined the difference between smart assets, smart accounts and dApp accounts and the basics of working with the functions of the verifier. Verifier features allow you to change the default account behavior. By default, they verify transaction signatures, but the verifier function allows you to set other "rules".
{-# STDLIB_VERSION 3 #-} {-# CONTENT_TYPE DAPP #-} {-# SCRIPT_TYPE ACCOUNT #-} letownerPublicKey = base58'H8ndsHjBha6oJBQQx33zqbP5wi8sQP7hwgjzWUv3q95M' @Verifier(tx) funcverify() = { matchtx { cases: SetScriptTransaction=>sigVerify(tx.bodyBytes, tx.proofs[0], ownerPublicKey) cased: DataTransaction=>true case_ =>false } }
Then we started adding coupons. We used one of the most important functions of dApp, which allows us to write data of any type to the blockchain in the form of key-value pairs - a data transaction. We combined it with a new transaction, invokeScript, used to call the called function in dApp from outside the blockchain.
The type of data transaction that we used during the course was adding coupons to the marketplace:
letdatajson = { "title": "t-shirt with , vote 1", "coupon_price": 10000000, "old_price": 1000000000, "new_price": 100000000, "address": "Universe", "description": "I want you to make love, not war, i know you've heard it before", "image": "https://bit.ly/2EXTghg" } it('add item', asyncfunction(){ letts = invokeScript({ dApp: dappAddress, call:{ function:"addItem", args:[ { type:"string", value: datajson.title }, { type:"integer", value: datajson.coupon_price }, { type:"string", value: JSON.stringify(datajson) } ]}, payment: [] }, accountSupplierSeed) lettx = awaitbroadcast(ts) awaitwaitForTx(tx.id) })
To process this data with the addItem function and to develop a purchase function and other options, we used a called function that the user can call from outside the blockchain. As a result, it can perform various tasks, for example, initiate a transfer of funds, write or update data in a dApp data warehouse, etc.
Here is an example of the called function used in the addItem function:
@Callable(i) funcaddItem(title: String, price: Int, data: String) = { letsupplierAddress = toBase58String(i.caller.bytes) letitem = getKeyItem(supplierAddress, title) if( price <= 0) thenthrow("purchase amount cannot be less than item price") elseif( getValueItemSupplier(item) !=NONE ) thenthrow("an item is already exist") else{ WriteSet([ DataEntry(getKeyItemSupplier(item), supplierAddress), DataEntry(getKeyItemPrice(item), price), DataEntry(getKeyItemData(item), data) ]) } }
Later, we developed a voting system that allows us to vote on the promotion or removal of certain products. In order to prevent outside influences on the voting process, she uses the 'Commit-Reveal' scheme.
The commit phase is used to collect encrypted votes using a hash function and a salt.
The βrevealβ phase is used to collect encrypted votes and compare their hashes.
Here is an example of the called function used here:
@Callable(i) funcvoteCommit(item: String, hash: String) = { letuser = toBase58String(i.caller.bytes) letcommits = getValueCommitsCount(item) letstatus = getValueItemStatus(item) if( commits >=VOTERS) thenthrow("reached max num of voters") elseif(getValueCommit(item, user) !=NONE) thenthrow("user has already participated") elseif(getKeyItemSupplier(item) ==NONE) thenthrow("item does not exist") elseif(status !=NONE && status !=VOTING) thenthrow("voting is not possible") else{ WriteSet([ DataEntry(getKeyCommit(item, user), hash), DataEntry(getKeyCommitsCount(item), commits +1), DataEntry(getKeyItemStatus(item),if(commits ==VOTERS) thenREVEAL elseVOTING) ]) } } >
What else did you learn from the course?
The course also included tokenization and non-fungible tokens (NFT) - tokens representing something unique and therefore not interchangeable.
The last lesson was about oracles. Since the blockchain cannot receive data from the outside world, we need oracles to send this data to it.
For our marketplace, oracles were needed to verify and, if necessary, blacklist a supplier who, for example, did not accept a sold coupon.
Here is an example:
funcgetExtValueItemWhiteListStatus(item:String) = { item +"_verifier_status" } letverifier = "3Mx9qgMyMhHt7WUZr6PsaXNfmydxMG7YMxv" letVERIFIED = "verified" letBLACKLISTED = "blacklist" @Callable(i) funcsetstatus(supplier: String, status: String) = { letaccount = toBase58String(i.caller.bytes) if( account !=verifier ) thenthrow("only oracle verifier are able to manage whitelist") elseif( status !=VERIFIED && status !=BLACKLISTED) thenthrow("wrong status") else{ WriteSet([ DataEntry(getExtValueItemWhiteListStatus(supplier), status) ]) } }
What was most useful to you?
The most useful part is the assignments. Thanks to them, the lecture material became clearer, and the knowledge that was just gained was consolidated by trial and error. Practical work with
IDE ,
explorer and
oracles was very useful.
How do you plan to use what you have learned in practice?
From the very beginning, I expected the course to help bring my project to the next level. The idea was to write
sign-web.app code on RIDE now. The existing version already has the functions of document certification, but thanks to RIDE, it can be significantly improved. The new version will be more flexible and understandable, it will have more functions, including certification of emails, agreements between several parties, etc.
The course also provided food for thought, and I had many new ideas. I am sure that the results will be manifested in the future.