DEV Community

Cover image for "Hola mundo!" en Web3 [Blockchain]
Ahmed Castro
Ahmed Castro

Posted on

"Hola mundo!" en Web3 [Blockchain]

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) y creamos nuestra carpeta de proyecto e instalamos las dependencias.

Si luego de ver este tutorial desas profundizar un poco Truffle abre este post en otra pestaña.

1. Lanzar un contrato en un blockchain local

Iniciemos creando un proyecto nuevo de Truffle.

mkdir MyProject
cd MyProject
npm install --save-dev truffle ganache-cli @truffle/hdwallet-provider
npm install --global lite-server
npx truffle init
Enter fullscreen mode Exit fullscreen mode

Ahora creemos nuestro contrato de "Hola mundo!"

contracts/MyContract.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.8.5;

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

    function setHello(string memory _hello) public {
        hello = _hello;
    }
}
Enter fullscreen mode Exit fullscreen mode

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

truffle-config.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
  }
};
Enter fullscreen mode Exit fullscreen mode

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

migrations/2_my_deploy.js

const MyContract = artifacts.require("MyContract");

module.exports = async function (deployer) {
  await deployer.deploy(MyContract);
};
Enter fullscreen mode Exit fullscreen mode

Lanzamos nuestro contrato en un blockchain local.

npx truffle compile
npx ganache-cli --deterministic #en otra consola
npx truffle migrate --network development
Enter fullscreen mode Exit fullscreen mode

2. HTML

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

client/index.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>
Enter fullscreen mode Exit fullscreen mode

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

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()
Enter fullscreen mode Exit fullscreen mode

Ahora podemos interactuar con el contrato desde javascript.

client/src/index.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 })
}
Enter fullscreen mode Exit fullscreen mode

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.

cd client
lite-server
Enter fullscreen mode Exit fullscreen mode

Gracias por ver este tutorial!

Sígueme en dev.to y en Youtube para todo lo relacionado al desarrollo en Blockchain en Español.

Discussion (0)