Intermediate

 

Deploy a Dapp with Taquito

Welcome to our tutorial on deploying a decentralized application (Dapp) with Taquito, a powerful JavaScript library for interacting with the Tezos blockchain network. In this tutorial, we will cover the process of using Taquito to build and deploy a decentralized application on the Tezos blockchain. We will walk through the process of writing, testing, and deploying a Dapp, as well as explain the key features and advantages of using Taquito.

By the end of this tutorial, you will have a solid understanding of how to use Taquito to build and deploy a decentralized application on the Tezos blockchain. You will also learn best practices for developing Dapps using Taquito and how to interact with them. This tutorial is ideal for developers and researchers interested in building and deploying decentralized applications on the Tezos blockchain using JavaScript and Taquito.

Initializing the deployment

Let’s start by installing the necessary dependencies :

mkdir deploy
touch deploy/main.ts
cd deploy
npx typescript --init --resolveJsonModule
yarn add typescript @taquito/taquito @taquito/signer @taquito/utils

Then, Taquito must be initialized and the signer provider set.

The basis of the project, therefore, looks like this :

// main.ts
import { TezosToolkit } from '@taquito/taquito';
import { InMemorySigner } from '@taquito/signer';

const RPC_URL = "https://hangzhounet.smartpy.io";

const deploy = async () => {
    try {
        const tezos = new TezosToolkit(RPC_URL);
        tezos.setSignerProvider(InMemorySigner('YOUR_PRIVATE_KEY'));



    } catch (err) {
        console.log(err);
    }
}

deploy();

Let’s run it with:

npx ts-node main.ts

If Taquito is correctly installed and configured, this should not raise any exception.

Compiling smart contracts

To be deployed with Taquito, the smart-contract must be compiled in Michelson in JSON format.

The ligo compiler allows this by passing the flag --michelson-format when compiling the contract:

ligo compile contract --michelson-format json raffle.ligo > contracts/raffle.json

The contract is now ready to be deployed. We can import it into our project :

// main.ts
...
import raffleJson from './contracts/raffle.json';
...

Taquito Origination

Defining the initial storage

A smart contract defines storage. When originated, the initial storage must be set and the storage must be compliant with the structure defined in the smart contract to be deployed: the names and types must be respected. It also allows you to work with types specific to Michelson, such as bigmaps.

We, therefore, need to import two additional functions :

import { MichelsonMap } from '@taquito/taquito';
import { buf2hex } from '@taquito/utils';

Below is the matching table between Javascript and LIGO.

LIGO

Javascript

List, Tuple, Set

[]

Big_map, Map

const bigMap = new MichelsonMap()
bigMap.set(key, values)
(from taquito module)

string, address

string

bytes

buf2hex(Buffer.from(string_to_convert))

int, nat, mutez

number

record

Object {}

timestamp

Date.now()

Here is what our initial storage should look like :

// main.ts
import { TezosToolkit, MichelsonMap } from '@taquito/taquito';
import { InMemorySigner } from '@taquito/signer';
import { buf2hex } from '@taquito/utils';

import raffleJson from './contracts/raffle.json';

const RPC_URL = "https://hangzhounet.smartpy.io";

const deploy = async () => {
    try {
        // Initialize Taquito
        const tezos = new TezosToolkit(RPC_URL);
        tezos.setSignerProvider(InMemorySigner('YOUR_PRIVATE_KEY'));

        // Initial storage definition
        const admin = 'YOUR_PUBLIC_KEY_HASH';  // Admin address, tz1...
        const closeDate = Date.now() + 10;    
        const jackpot = 100;
        const description = "This is an incredible Raffle.";
        const players = [] as any[];
        const soldTickets = new MichelsonMap();
        const raffleIsOpen = true;
        const winningTicketHash = buf2hex(Buffer.from("ec85151eb06e201cebfbb06d43daa1093cb4731285466eeb8ba1e79e7ee3fae3"));

        const initialStorage = {
            "admin": admin,
            "close_date": closeDate.toString(),
            "jackpot": jackpot,
            "description": description,
            "players": players,
            "sold_tickets": soldTickets,
            "raffle_is_open": raffleIsOpen,
            "winning_ticket_number_hash": winningTicketHash
        }

    } catch (err) {
        console.log(err);
    }
}

deploy();

Any type and structure change in the LIGO smart contract storage must be mirrored in the initialStorage variable. This way, the evolution of the storage used can be versioned.

Deploying the contract

Originations can be sent with tezos.contract.originate. It returns a Promise<OriginationOperation<DefaultContractType>>.

An OriginationOperation contains the information about this origination. It also has a confirmation method. This method can wait for several confirmations on demand.

Let’s deploy our contract with this function by setting your code in JSON Michelson format and our initial storage :

// main.ts
import { TezosToolkit, MichelsonMap } from '@taquito/taquito';
import { InMemorySigner } from '@taquito/signer';
import { buf2hex } from '@taquito/utils';

import raffleJson from './contracts/raffle.json';

const RPC_URL = "https://hangzhounet.smartpy.io";

const deploy = async () => {
    try {
        // Initialize Taquito
        const tezos = new TezosToolkit(RPC_URL);
        tezos.setSignerProvider(InMemorySigner('YOUR_PRIVATE_KEY'));

        // Initial storage definition
        const admin = 'YOUR_PUBLIC_KEY_HASH'; // Admin address, tz1...
        const closeDate = Date.now() + 10;    
        const jackpot = 100;
        const description = "This is an incredible Raffle.";
        const players = [] as any[];
        const soldTickets = new MichelsonMap();
        const raffleIsOpen = true;
        const winningTicketHash = buf2hex(Buffer.from("ec85151eb06e201cebfbb06d43daa1093cb4731285466eeb8ba1e79e7ee3fae3"));

        const initialStorage = {
            "admin": admin,
            "close_date": closeDate.toString(),
            "jackpot": jackpot,
            "description": description,
            "players": players,
            "sold_tickets": soldTickets,
            "raffle_is_open": raffleIsOpen,
            "winning_ticket_number_hash": winningTicketHash
        }

        const origination = await tezos.contract.originate({
            code: raffleJson,
            storage: initialStorage,
          });
        
          await origination.confirmation();
          const contract = await origination.contract();

          console.log(`Operation Hash: ${origination.hash}`);
          console.log(`Contract Address : ${contract.address}`);
    } catch (err) {
        console.log(err);
    }
}

deploy();

Run the script and retrieve the operation hash and the contract address :

npx ts-node main.ts
Operation Hash: oo9jUpwnfCnNqywT5dqFuoMhWgn9Ve3bKYqivNUy1jn3t2kKTb8
Contract Address : KT1Dkdiju5crR6qQMy9ozzWvTaVHBTA476gb

We can now check the transaction and the contract on an explorer.

With this, you complete this workshop successfully!!