What is Tezos? Tezos is a blockchain network that supports formally verified smart contracts and has a unique governance feature where token holders can vote on-chain on protocol upgrades. These upgrades allow Tezos to evolve forklessly and in a decentralized manner.
What are Smart Contracts? These are small and readable programs that run on the blockchain and can transfer funds based on their logic.
What are DApps?. Distributed Applications are web applications that run in the browser and interact with smart contracts through blockchain nodes.
For this tutorial we will program a simple Hello World application: a good old-fashioned guestbook. It has only entries, authors and timestamps and consists of 1 smart contract.
Note: the Tezos tooling ecosystem is rather decentralized, this means that there are usually several teams building different tools serving a similar purpose. Here I will suggest the ones that have worked for me, but bear in mind that there often exist equally good alternatives.
To deploy the contract to the testnet, we need to interact with a node. For this we will usetezos-client
. Unofficial prebuilt binaries are found here, for e.g. macOS:$ brew tap serokell/tezos-packaging https://github.com/serokell/tezos-packaging.gitWe will be using this cli client often, lets create an alias for your shell with RPC parameters for tezos-client:
$ brew install tezos-client
alias mainnet='tezos-client --endpoint https://mainnet-tezos.giganode.io/'Create an account (will be stored under
alias testnet='tezos-client --endpoint https://testnet-tezos.giganode.io/'
~/.tezos-client
):$ tezos-client gen keys myAccountWe need testnet funds. There are some free faucets, I recommend this Telegram Bot. When funds arrive, check the balance:
$ tezos-client list known addresses
$ testnet get balance for myAccount
There are several choices of tools you can find on the official Develper Portal, for this tutorial we will use SmartPy, a Python-based language.
Install SmartPy:$ sh <(curl -s https://smartpy.io/cli/install.sh)Create a
guestbook.py
file:import smartpy as sp
class Guestbook(sp.Contract):
def __init__(self):
self.init(
dates = sp.list([]),
entries = sp.list([]),
authors = sp.list([])
)
@sp.entry_point
def add_entry(self, params):
self.data.dates.push(sp.now)
self.data.entries.push(params.e)
self.data.authors.push(params.a)
# Tests
@sp.add_test(name = "Guestbook")
def test1():
scenario = sp.test_scenario()
scenario.h1("Welcome to Guestbook")
c1 = Guestbook()
scenario += c1
scenario += c1.add_entry(a = 'alice', e = 'hello from alice')
scenario += c1.add_entry(a = 'bob', e = 'hello from bob')
scenario += c1.add_entry(a = 'charles', e = 'hello from charles')
The contract file has one default entrypoint and the contract's storage has three lists. To compile it, we call:$ ~/smartpy-cli/SmartPy.sh test guestbook.py output
The output folder now contains Michelson code, the native stack-based language of smart contracts on Tezos, as well as the output of the tests.
Deploy the generated tz file (Tip: use--dry-run
to simulate first):$ testnet originate contract guestbook transferring 0 from myAccount \ running output/Guestbook/step_001_cont_0_contract.tz \ --force --fee 0.001 --init "Pair {} (Pair {} {})" --burn-cap 0.125
Listing contracts with testnet list known contracts
should show the guestbook contract.
$ testnet call guestbook from myAccount \ --arg '(Pair "alice" "hi from alice")' \ --burn-cap 0.0085Inspect your contract's KT address on Better Call Dev to see the operations.
Install dependencies:
$ yarn add @taquito/taquito @taquito/beacon-wallet
Read the storage of the contract:
import { TezosToolkit } from '@taquito/taquito'
const contractAddress = 'KT1...'
const Tezos = new TezosToolkit('https://edonet-tezos.giganode.io')
const contract = await Tezos.contract.at(contractAddress)
const storage = await this.contract.storage()
// storage should now have "hi from alice"
Send a new operation with the help of our wallet extension:import { BeaconWallet } from '@taquito/beacon-wallet'
const wallet = new BeaconWallet({
name: 'Tezos Guestbook'
})
await wallet.requestPermissions({
network: {
type: 'edonet'
}
})
Tezos.setProvider({ wallet })
const contract = await Tezos.wallet.at(contractAddress)
const operation = await (contract.methods.default(
// parameter order should match the entrypoint in the smart contract
author,
message
).send())
const opResult = await operation.confirmation()
if (opResult.completed) {
// Fetch the contract storage again to see the new entry
} else {
// An error has occurred
}
DApps usually consist of several smart contracts that interact with each other, but simpler ones could consist of just one. In this tutorial we explored how to build a Hello World variant of a DApp.
Try it out with your idea and see for yourself how reasonably easy it is. I can not compare with Solidity, as I have not used it.
To me it seems the Tezos ecosystem has matured: it supports multiple high-level smart contract languages, there are several choices for libraries, frameworks and wallets. There are already interesting DApps in the DeFi and NFT spaces: Dexter, Kolibri, HicEtNunc, to name a few.
The complete code of the DApp is available on Github.
A PDF of this article has been minted as a 10-edition NFT that you can collect: https://www.hicetnunc.xyz/objkt/23525
You might need to refresh this page a few times for the Discus comments section to appear below.