Taquito

Taquito is a TypeScript library suite for development on the Tezos blockchain.
Docusaurus with Keytar

Integration in DApps#

The Temple wallet, used in the DApps, integrates Taquito which is then used to interact with the smart contract.

The Taquito object is retrieved with a mecanism defined in the file /src/dapps.js. All DApps use a global state managed with the constate library.

dapp.js registers in the constate global state an accessor useTezos, so that any module can retrieve it easily, without passing it down from root React element:

import { useTezos } from '../dapp';
const ReactComponent = (props) => {
const tezos = useTezos();
...
}

As a side note, here is the way to retrieve the account address (public key) the user has signed in with:

import { useAccountPkh } from '../dapp';
const ReactComponent = (props) => {
const account = useAccountPkh();
...
}

Note that the user account is managed by the Temple wallet, not by Taquito. The wallet internally passes the account's private key to Taquito to sign transactions.

Contract origination#

Taquito originates contracts provided in the Micheline format, a json version of Michelson.

The Completium CLI command to generate Micheline from contract.arl:

$ completium-cli generate javascript contract.arl > contract.js

The generated contract.js file exports:

  • the Micheline/Json code of the contract
  • the getStorage methode to build the initial storage

These two elements are passed to the Taquito's originate method:

import { code, getStorage } from 'contract.js';
try {
const operation = await tezos.wallet.originate({
code: code,
init: getStorage(...)
}).send();
console.log(`Waiting for confirmation of origination...`);
const contract = await operation.contract();
console.log(`Origination completed for ${contract.address}.`);
} catch (error) {
console.log(`Error: ${JSON.stringify(error, null, 2)}`);
}

Examples of contract origination are found is the following DApps:

DAppOrigination description
Online purchaseThe escrow contract for payment is originated when customers decides to purchase.
Zero-coupon-bondThe Zero-coupon bond contract is originated when contract parameters are set in the editor.

Call contract#

It is very straightforward to call contracts entry points with Taquito.

Basics#

For example, the Idea Box DApp's smart contract, developed in Archetype language, defines an entry point vote to vote for an idea:

entry vote(n : nat, weight : nat) {
require {
r2 : voter.contains(caller);
r3 : voter[caller].remaining >= weight;
r4 : state = Activated;
}
effect {
voter[caller].remaining -= weight;
idea[n].nbvotes += weight;
}
}

The entry point requires two natural integer parameters:

  • the idea identifier
  • the weight the user wishes to associate to the vote (max. 5)

The following code calls the vote entry point:

const contract = await tezos.wallet.at(contractAddress);
const operation = await contract.methods.vote(id, weight).send();
console.log(`waiting for ${operation.opHash} to be confirmed`);
await operation.receipt();

Note that while the contract defines parameters as nat (natural integers), the javascript type is simply integer; Taquito emits an error if the conversion to Michelson type is not possible.

Typically here an error is emitted if -1 is passed as argument for example.

Transfer amount#

Some entry points require to send an amount of tez for the contract to execute properly according to the business logic.

For example, the start entry point of the Connected Object DApp requires to transfer some Tez to switch on the bulb. The amount is passed as argument of the send method:

import { UnitValue } from '@taquito/taquito';
const contract = await tezos.wallet.at(contractAddress);
const operation = await contract.methods.start(UnitValue).send({ amount : price });
console.log(`waiting for ${operation.opHash} to be confirmed`);
await operation.receipt();

Note that UnitValue is necessary to pass when the entry point does not have any argument.

The default amount unit is Tez. It is possible to pass Mutez (1 Tez = 10^6 Mutez) by adding mutez: true to the send argument.

Several Transactions#

It is possible to execute several transactions in one operation.

For example in the DEX DApp, the exchange process requires calling two contracts: the FA 1.2 and the DEX. The following code illustrates how to execute that:

// FA 1.2 transaction definition
const fa12 = await tezos.wallet.at(fa12address);
const fa12params = fa12.methods.approve(UnitValue).toTransferParams();
fa12params.kind = OpKind.TRANSACTION;
// DEX transaction definition
const dex = await tezos.wallet.at(dexaddress);
const dexparams = dex.methods.exchange(UnitValue).toTransferParams();
dexparams.kind = OpKind.TRANSACTION;
// Group them in a batch operation and send
const batch = await tezos.wallet.batch([fa12params, dexparams]);
const operation = await batch.send();
await operation.receipt();

The parameters of approve and exchange have been simplified to UnitValue for demo purpose.

Read contract storage#

Variables#

For example in the Connected Object DApp, it is necessary to read the dates of service to know whether the object is currently in use.

These variables are declared in the smart contract with the Archetype language:

variable dateofstop : date = now
variable dateofstart : date = now
variable value : int = 0tz

These values are stored in the contract storage (click here to view an instance in Better Call dev indexer).

Taquito provides the contract storage as a POJO for direct access to the contract data:

var contract = await tezos.contract.at(contractAddress);
var storage = await contract.storage();
const dateofstart = new Date(storage.dateofstart);
const dateofstop = new Date(storage.dateofstop);
const value = storage.value.toNumber();

Since Tezos can store arbitrary large number values, Taquito provides the number values as bignumber objects to be converted with toNumber.

Collection of assets#

For example in the the Idea Box DApp, the smart contract stores the idea and the votes.

The collection of ideas is declared in Archetype language the following way:

asset idea {
id : nat;
title : bytes;
desc : bytes;
nbvotes : nat = 0;
creation : date;
author : address;
}

The asset collection is compiled to a (Michelson) map from id to a 'record' { title; desc; nbvotes; creation; author }. It is possible to iterate over the map with the forEach operator:

var contract = await Tezos.contract.at(contractAddress);
var storage = await contract.storage();
storage.idea.forEach((i, k, _) => {
ids.push({
id: k,
title: fromHexString(i.title),
desc: fromHexString(i.desc),
author: i.author,
nbvotes: parseInt(i.nbvotes,10),
creation: (i.creation+'').substring(0,10),
winner: false
});
});

The code above stores each id in a local javascript list of records ids. k is the idea identifier (named id in the Archetype contract).