Web3js/Taquito differences

Web3js and Taquito have a common goal: connecting dapps to the Ethereum and Tezos blockchain (respectively) and thus implement similar approaches. However, these approaches are also different due to the nature of the Ethereum and the Tezos blockchains.

A comparison of the methods implemented by Web3js and Taquito can put in perspective their similarities and differences.

Installation

Web3js: npm install web3

Taquito: npm install @taquito/taquito

Web3js comes as a single package containing all the necessary tools to connect to the Ethereum blockchain while Taquito is made of various packages that you can install and import whenever you need them.

Connection

Web3js:

import Web3 from 'web3';
const web3 = new Web3(Web3.providers.HttpProvider('http://localhost:9545'));

Taquito:

import { Tezos } from @taquito/taquito;
Tezos.setProvider({rpc: "http://localhost:9545"});

The Web3js package exports a class that needs to be instantiated before being used. The difference between Web3 and web3 is a common source of errors in Ethereum development. Taquito exports a ready-to-use singleton object conveniently called Tezos. However, if you want to instantiate and initialize it yourself, it is also possible to import TezosToolkit from Taquito and write const Tezos = new TezosToolkit(options);, which is similar to the Web3js code.

Get account balance

Web3js:

const balance = await web3.eth.getBalance('account_address');

Taquito

const balance = await Tezos.tz.getBalance('account_address');

Both Web3js and Taquito use the getBalance method with the account address to fetch its balance from the network.

Transfer tokens

Web3js:

const op = await web3.eth.sendTransaction({
from: 'sender_address',
to: 'recipient_address',
value: 'amount_in_wei',
});

Taquito:

const op = await Tezos.wallet.transfer({
to: 'recipient_address',
amount: 'amount_in_tez',
});
await op.confirmation();

Web3js and Taquito allow the transfer of tokens from one address to another in a similar fashion. The transaction on Ethereum returns a promise with receipt/event emitter and resolves when the receipt is available. The transaction on Tezos returns a WalletOperation promise with a confirmation method that waits for the number of confirmations specified as a parameter (default 1) before resolving.

Create a contract instance

Web3js

const contract = new web3.eth.Contract(JSON_ABI);

Taquito:

const contract = await Tezos.wallet.at('contract_address');

The two approaches are radically different here: Web3js constructs the contract interface from the "ABI" that's shipped with the dapp while Taquito fetches the contract structure directly from the blockchain to construct the interface.

Get the "counter" value from the contract storage

Web3js:

const counter = await contract.methods.getCounter().call();

Taquito:

const counter = await contract.storage();

This is another point that shows how different the Ethereum and the Tezos blockchains are. On Ethereum, the contract has to implement getter functions to return values from its storage and make them available to dapps. On Tezos, the whole storage is always available and developers don't have to add view functions to their contracts to make the values in the storage available.

Call the increment method on the contract instance

Web3js:

const receipt = await contract.methods.increment(1).send();

Taquito:

const op = await contract.methods.increment(1).send();
await op.confirmation();

Calling functions/entrypoints is very similar on Ethereum and Tezos. Just remember that the function doesn't return any value from the blockchain on Tezos.

Deploy/originate a smart contract

Web3js:

const newInstance = await myContract
.deploy({
data: 'contract_code',
arguments: 'constructor_arguments',
})
.send();
const contractAddress = newInstance.options.address;

Taquito:

const op = await Tezos.wallet
.originate({
code: 'parsed_michelson',
storage: 'initial_storage',
})
.send();
const contract = await op.contract();
const contractAddress = contract.address;

Both functions returns a new instance of the contract from which the address of the newly deployed/originated contract can be found.

Check if the wallet injected an outdated version of the library in the browser

Web3js:

if(typeof window.web3 !== undefined){
// MetaMask injected web3
...
} else {
...
}

Taquito:

Nope;

Full code to connect to the network and send a transaction to a smart contract

Web3js:

import Web3 from 'web3';
let web3;
if (typeof window.web3 !== 'undefined') {
web3 = new Web3(window.web3.currentProvider);
} else {
web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
}
const userBalance = await web3.eth.getBalance('0x_address');
const contract = new web3.eth.Contract('contract_ABI', 'contract_address');
const counter = await contract.methods.counter().call();
const receipt = await contract.methods.increment(counter + 1).send();

Taquito:

import { Tezos } from '@taquito/taquito';
const wallet = Tezos.setProvider({ rpc: 'http://localhost:8732', wallet }); // use the wallet of your choice
const userBalance = await Tezos.tz.getBalance('tz_address');
const contract = await Tezos.wallet.at('contract_address');
const counter = await contract.storage();
const op = await contract.methods.increment(counter + 1).send();
await op.confirmation();