"Hola mundo!" en Web3.js [Blockchain]
Tags: html, blockchain, solidity, javascript
Published: 2021-07-15 19:17:08

---
title: "Hola mundo!" en Web3.js [Blockchain]
published: true
description: 
tags: #html, #blockchain, #solidity, #javascript
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yrmzvjbutci2hdsx3inl.png
---

{% youtube 7gg-bRGM_og %}

Web3 es la librería que necesitamos para comunicarnos con smart contracts lanzados en cualquier blockchain compatible con la Ethereum Virtual Machine.

Antes de iniciar asegurate de instalar node (te recomiendo que lo instales [via nvm](https://heynode.com/tutorial/install-nodejs-locally-nvm/)) y creamos nuestra carpeta de proyecto e instalamos las dependencias.

Si luego de ver este tutorial desas profundizar un poco Truffle abre [este post](https://dev.to/turupawn/truffle-hola-mundo-en-un-blockchain-de-prueba-475g) en otra pestaña.

## 1. Lanzar un contrato en un blockchain local

Iniciemos creando un proyecto nuevo de Truffle.

```bash
mkdir MyProject
cd MyProject
npm install --save-dev truffle ganache-cli @truffle/hdwallet-provider
npm install --global lite-server
npx truffle init
```

Ahora creemos nuestro contrato de "Hola mundo!"

`contracts/MyContract.sol`
```solidity
// SPDX-License-Identifier: MIT

pragma solidity 0.8.5;

contract MyContract {
    string public hello = "Hola mundo!";

    function setHello(string memory _hello) public {
        hello = _hello;
    }
}
```

En nuestro truffle config seteamos el `contracts_build_directory` y la versión de solidity a `0.8.5`.

`truffle-config.js`
```js
module.exports = {
  contracts_build_directory: "./client/contracts",
  networks: {
    development: {
      host: "127.0.0.1",     // Localhost (default: none)
      port: 8545,            // Standard Ethereum port (default: none)
      network_id: "*",       // Any network (default: none)
    },
  },
  compilers: {
    solc: {
      version: "0.8.5",    // Fetch exact version from solc-bin (default: truffle's version)
    }
  },
  db: {
    enabled: false
  }
};
```

Que no se nos olvide el script de la migración.

`migrations/2_my_deploy.js`
```js
const MyContract = artifacts.require("MyContract");

module.exports = async function (deployer) {
  await deployer.deploy(MyContract);
};
```

Lanzamos nuestro contrato en un blockchain local.

```bash
npx truffle compile
npx ganache-cli --deterministic #en otra consola
npx truffle migrate --network development
```

## 2. HTML

Agregamos un archivo de HTML para poder interactuar con el contrato.

`client/index.html`
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
</head>
<body>
  <h1>Ejemplo Web3</h1>
  <input id="input_hello" /><br/>
  <button onclick="setHello()">Set hello</button><br>
  <button onclick="getHello()">Get hello</button><br/>
  <p id="p_hello"></p>

  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/web3/1.3.5/web3.min.js"></script>
  <script type="text/javascript" src="src/utils.js"></script>
  <script type="text/javascript" src ="src/index.js"></script>
</body>
</html>
```

## 3. Javascript

Todo lo necesario para comunicarnos con el blockchain desde javascript. En este archivo nos conectamos a Metamask, leemos el account de nuestra wallet y leemos el contrato que está guardado en `client/contracts/MyContract.json`. Finalmente todo quedará guardado en las variables `web3`, `accounts` y `contract`.

`client/src/utils.js`
```js
const getWeb3 = async () => {
  return new Promise((resolve, reject) => {
    console.log(document.readyState)
    if(document.readyState=="complete")
    {
      if (window.ethereum) {
        const web3 = new Web3(window.ethereum)
        try {
          // ask user permission to access his accounts
          (async function(){
            await window.ethereum.request({ method: "eth_requestAccounts" })
          })()
          resolve(web3)
        } catch (error) {
          reject(error)
        }
      } else {
        reject("must install MetaMask")
      }
    }else
    {
      window.addEventListener("load", async () => {
        if (window.ethereum) {
          const web3 = new Web3(window.ethereum)
          try {
            // ask user permission to access his accounts
            await window.ethereum.request({ method: "eth_requestAccounts" })
            resolve(web3)
          } catch (error) {
            reject(error)
          }
        } else {
          reject("must install MetaMask")
        }
      })
    }
  })
}

const getContract = async (web3) => {
  const data = await getJSON("./contracts/MyContract.json")
  const netId = await web3.eth.net.getId()
  const deployedNetwork = data.networks[netId]
  const contract = new web3.eth.Contract(
    data.abi,
    deployedNetwork && deployedNetwork.address
  )
  return contract
}

function getJSON(url) {
  return new Promise(resolve => {
    var xhr = new XMLHttpRequest()
    xhr.open("GET", url, true)
    xhr.responseType = "json"
    xhr.onload = function () {
      resolve(xhr.response)
    }
    xhr.send()
  })
}

async function loadApp() {
  var awaitWeb3 = async function () {
    web3 = await getWeb3()
    web3.eth.net.getId((err, netId) => {
      var awaitContract = async function () {
        contract = await getContract(web3)
        var awaitAccounts = async function () {
          accounts = await web3.eth.getAccounts()
          console.log("Web3 loaded")
        }
        awaitAccounts()
      }
      awaitContract()
    })
  }
  awaitWeb3()
}

loadApp()
```

Ahora podemos interactuar con el contrato desde javascript.

`client/src/index.js`
```js
var contract
var accounts
var web3

const getHello = async () => {
  hello = await contract.methods.hello().call()
  document.getElementById("p_hello").innerHTML = hello
}

const setHello = async () => {
  var hello = document.getElementById('input_hello').value
  const result = await contract.methods.setHello(hello)
  .send({ from: accounts[0], gas: 400000 })
}
```

Para interactuar vía Metamask debes configurar tu metamask a que apunte a `http://127.0.0.1:8545` en el chain id `1337` con una llave privada listada en el resultado del comando `npx ganache-cli --deterministic`. Una vez hecho esto levantamos un servidor web desde la carpeta `./client`.

```bash
cd client
lite-server
```

**Gracias por ver este tutorial!**

Sígueme en dev.to y en [Youtube](https://www.youtube.com/channel/UCNRB4tgwp09z4391JRjEsRA) para todo lo relacionado al desarrollo en Blockchain en Español.