La versión más reciente de web3.js, la 4.x, acaba de ser presentada. En esta guía, profundizaremos en la integración de web3.js en HTML para Transferir, Mintear NFTs, así como para consultar la Blockchain. Varias características dentro de la documentación de web3.js v 1.10.0 van a ser desaprobadas (deprecated), por lo tanto, hemos recopilado los métodos más actualizados para este tutorial de web3.js. Nos abstendremos de utilizar un framework como React js. Al no usar ningún framework, nos vemos obligados a adquirir una comprensión más profunda de los conceptos fundamentales involucrados en el desarrollo de Dapps. Este enfoque práctico te ayuda a construir una base sólida para tus habilidades de desarrollo en la blockchain. Simplemente sigue las instrucciones paso a paso, copia y pega los códigos, y lee los fragmentos de código proporcionados. Esto es lo que cubrimos en este tutorial:
- Aspectos Destacados de la Migración a Web3.js 4.x
- Primeros Pasos: Web3.js
- Parte 1: Conectar a MetaMask
- Parte 2: Mostrar Información de la Cuenta
- Parte 2: Enviar Transacción
- Parte 3: Interactuar con un Smart Contract
Proporcionamos ejemplos y elementos visuales a lo largo de este tutorial para ilustrar los conceptos que se están discutiendo.
Aspectos Destacados de la Migración a Web3.js 4.x
Esta guía te lleva a través de algunos de los cambios de código significativos para la migración a Web3.js 4.x.
Breaking Changes
1. Importación de Módulos
// Web3.js 1.x import
const Web3 = require('web3');
// Web3.js 4.x import
const { Web3 } = require('web3');
En Web3.js 4.x, hemos cambiado a la sintaxis de desestructuración para importar el objeto Web3.
2. Proveedores por Defecto
En Web3.js 4.x, los valores por defecto de web3.givenProvider y web3.currentProvider son undefined. Anteriormente, eran null cuando web3 se instanciaba sin un proveedor.
// Defaults to undefined in Web3.js 4.x, previously null
console.log(web3.givenProvider);
console.log(web3.currentProvider);
Si estás utilizando MetaMask, se recomienda pasar window.ethereum directamente al constructor de Web3, en lugar de utilizar Web3.givenProvider.
// Instantiate Web3 with MetaMask providerconst web3 = new Web3(window.ethereum);
3. Callbacks en Funciones
Los callbacks ya no son compatibles en las funciones, a excepción de los event listeners. Aquí hay un ejemplo del uso no válido de callbacks en Web3.js 4.x, que era válido en la versión 1:
// INVALID in Web3.js 4.x
web3.eth.getBalance("0x407d73d8a49eeb85d32cf465507dd71d507100c1", function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
}
});
Cambios Menores
1. Instanciar un Smart Contract
En Web3.js 4.x, debes usar la palabra clave new para instanciar un objeto web3.eth.Contract().
// Web3.js 1.x
const contract = web3.eth.Contract(jsonInterface, address);
// Web3.js 4.x
const contract = new web3.eth.Contract(jsonInterface, address);
2. getBalance
En Web3.js 4.x, getBalance devuelve un BigInt en lugar de un String. Para ver la guía de migración completa, visita la documentación de web3.js: https://web3js.org/#/
Primeros Pasos: Web3.js
Crea una carpeta con la siguiente estructura de directorio:
├── directory/
│ ├── index.html
│ ├── main.js
│ ├── styles.css
Dónde descargar web3.js:
- Enlace CDN: web3.js
Encuentra este proyecto en:
- Enlace del proyecto en Github: https://github.com/AymericRT/web3.js.git
Parte 1: Conectar a MetaMask
Ahora crearemos un botón que establezca una conexión con MetaMask. Los códigos del frontend se colocarán en index.html y los códigos javascript de web3.js en main.js
Index.html
Los códigos a continuación contienen lo siguiente:
- Plantilla base (boilerplate) de HTML
- Botón de MetaMask
- Etiqueta Script del paquete CDN de web3.js
- Etiqueta Script de main.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Web3.js Example</title>
<link rel="stylesheet" href="./styles.css" />
<script
src="https://cdnjs.cloudflare.com/ajax/libs/web3/4.0.1-alpha.5/web3.min.js"
integrity="sha512-NfffVWpEqu1nq+658gzlJQilRBOvjs+PhEKSjT9gkQXRy9OfxI2TOXr33zS7MgGyTpBa5qtC6mKJkQGd9dN/rw=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
</head>
<body>
<main>
<p id="status1" class="status" style="color: red">disconnected</p>
<p id="status2" style="color: white"></p>
<div class="maincontainer">
<!-- Connect Wallet -->
<div class="container">
<div class="buttonswrapper">
<div class="buttonswrapperGrid">
<button id="metamask" class="button28">MetaMask</button>
</div>
</div>
</div>
<!-- Account Info Button -->
<!-- Send Transaction -->
<!-- Mint -->
</div>
</main>
<script src="./main.js"></script>
</body>
</html>
Explicación de los fragmentos de código HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/web3/4.0.1-alpha.5/web3.min.js"
integrity="sha512-NfffVWpEqu1nq+658gzlJQilRBOvjs+PhEKSjT9gkQXRy9OfxI2TOXr33zS7MgGyTpBa5qtC6mKJkQGd9dN/rw=="
crossorigin="anonymous" referrerpolicy="no-referrer">
Esta etiqueta script en la sección
se utiliza para cargar la biblioteca CDN de web3.js.Esto es el equivalente a const { Web3 } = require(‘web3’);
<script src="./main.js"></script>
Esto carga nuestras funciones de “main.js” en el HTML. La mejor práctica es colocarlo al final del body para evitar acceder a elementos del DOM antes de que se rendericen.
Styles.css
Copia y pega los códigos css de Github: Enlace de Github al archivo: https://github.com/AymericRT/web3.js/blob/master/styles.css
Archivo Main.js
En el archivo main.js, incorporaremos las funciones de javascript necesarias para activar el botón de MetaMask. A continuación, se presentan tres funciones principales:
- Event Listener para el Botón “metamask”
- Tras un evento de clic, verifica si MetaMask está disponible y conectado.
- En caso afirmativo, llama a la función ConnectWallet.
- De lo contrario, registra un mensaje de error en la consola y actualiza el estado en la página web para indicar la ausencia de MetaMask.
- checkMetaMaskAvailability()
- La función se utiliza para determinar si una extensión de navegador de MetaMask está presente y conectada.
- Verifica la existencia de window.ethereum e intenta solicitar acceso a las cuentas de MetaMask a través de ConnectMetaMask().
- Si se concede el acceso a la cuenta, la función devuelve true, indicando una conexión exitosa. De lo contrario, registra un mensaje de error y devuelve false.
- ConnectMetaMask();
- Esta función es responsable de conectarse a MetaMask.
- Intenta solicitar acceso a las cuentas de MetaMask utilizando eth_requestAccounts.
Contrasta las explicaciones anteriores con los códigos a continuación.
const web3 = new Web3(window.ethereum);
// Function to check if MetaMask is available
async function checkMetaMaskAvailability() {
if (window.ethereum) {
try {
// Request access to MetaMask accounts
await window.ethereum.request({ method: "eth_requestAccounts" });
return true;
} catch (err) {
console.error("Failed to connect to MetaMask:", err);
return false;
}
} else {
console.error("MetaMask not found");
return false;
}
}
// Event listener for MetaMask button
document.getElementById("metamask").addEventListener("click", async () => {
const metaMaskAvailable = await checkMetaMaskAvailability();
if (metaMaskAvailable) {
await ConnectWallet();
} else {
// MetaMask not available
console.error("MetaMask not found");
// Update status
document.getElementById("status1").innerText = "MetaMask not found";
document.getElementById("status1").style.color = "red";
}
});
//Function to connect to MetaMask
async function ConnectWallet() {
try {
// Request access to MetaMask accounts
await window.ethereum.request({ method: "eth_requestAccounts" });
// Update status
document.getElementById("status1").innerText = "Connected to MetaMask";
document.getElementById("status1").style.color = "green";
} catch (err) {
// Handle error
console.error("Failed to connect to MetaMask:", err);
// Update status
document.getElementById("status1").innerText = "Failed to connect to MetaMask";
document.getElementById("status1").style.color = "red";
}
}
Fragmentos de Código Importantes: Conectar a MetaMask
web3.js window.ethereum
const web3 = new Web3(window.ethereum);
web3 es una nueva instancia de la biblioteca Web3.js.
Al asignar window.ethereum al constructor de Web3, la variable web3 utiliza el proveedor de Ethereum proporcionado para interactuar con la red Ethereum.
web3.js request Accounts
await window.ethereum.request({ method: "eth_requestAccounts" });
Este código solicita acceso a las cuentas de Ethereum del usuario en la aplicación web utilizando el método eth_requestAccounts.
Ejecuta tu servidor
En tu terminal, navega a tu directorio y ejecuta este comando de Python; desplegará automáticamente tu servidor en el puerto 8000.
python -m SimpleHTTPServer 8000
Así es como debería verse tu sitio web en localhost:8000

Parte 2: Mostrar Información de la Cuenta
Ahora que nuestro MetaMask está conectado, somos capaces de consultar la blockchain para obtener detalles esenciales de la cuenta, como la dirección de la cuenta conectada, el saldo y las tarifas de red actuales. Crearemos un botón para esta funcionalidad y lo llamaremos “Account_Information”.
Index.html
Inserta el botón “account_Information” debajo del comentario.
<!-- Account Information Button -->
<div class="secondcontainer">
<button id="accountbutton" class="button49">
Account Information
</button>
</div>
Main.js
Escribiremos una función que obtenga datos de MetaMask. Los datos mostrarán lo siguiente:
- Dirección de la cuenta
- Saldo de la cuenta
- Las tarifas de red actuales
Las dos funciones principales requeridas son:
- Event Listener para el Botón Account Information
- Tras un evento de clic, verifica si MetaMask está disponible y conectado.
- En caso afirmativo, llama a la función AccountInfo().
- De lo contrario, registra un error y actualiza el estado de la página web.
- AccountInformarion();
- Esta función es responsable de obtener datos de la Wallet de Ethereum.
- Recupera la dirección de la cuenta utilizando el método web3.eth.getAccounts().
- El saldo de la cuenta se obtiene a través del método web3.eth.getBalance(from).
- Adicionalmente, recupera el precio actual del gas llamando al método web3.eth.getGasPrice().
// Event Listener for Account Information
document.getElementById("accountbutton").addEventListener("click", async () => {
const metaMaskAvailable = await checkMetaMaskAvailability();
if (metaMaskAvailable) {
await AccountInformation();
}
});
//Function to call the Account Information
async function AccountInformation() {
const account = await web3.eth.getAccounts();
const from = account[0];
const balanceInWei = await web3.eth.getBalance(from);
const balanceInEth = web3.utils.fromWei(balanceInWei, "ether");
const gasPrice = await web3.eth.getGasPrice();
const gasPriceInEth = web3.utils.fromWei(gasPrice, "ether");
// Display the account information
document.getElementById("status2").innerText ="Account Address: " + from + "\nBalance: " + balanceInEth + " ETH" +"\nGas Price: " + gasPriceInEth;
document.getElementById("status2").style.color = "white";
}
Fragmentos de Código Importantes: Mostrar Información de la Cuenta
web3.js get Accounts
const account = await web3.eth.getAccounts() //returns list of account
const from = account[0]; // gets the first account in the list
El método getAccounts() devuelve una lista de las cuentas que controla el nodo. Básicamente, devuelve las cuentas conectadas de MetaMask.
El primer elemento de la lista representará la cuenta principal conectada.
web3.js get Balance
web3.eth.getBalance(from)
El método getBalance() obtiene el saldo de la dirección de la cuenta pasada como parámetro en Wei. Ten en cuenta que 1 Ether equivale a 10^18 Wei.
web3.js get Gas Price
web3.eth.getGasPrice()
El método getGasPrice() recupera el precio actual del gas en Wei para las transacciones en la red Ethereum.
web3.utils.fromWei(balanceInWei, "ether")
Este método convierte tu saldo de unidades Wei a Ether. Si deseas convertirlo a GWEI, simplemente cambia “ether” por “gwei”.

Parte 3: Enviar Transacción de Ether
Enviar una Transacción requiere los siguientes argumentos:
- Dirección del Remitente
- Dirección del Destinatario
- Cantidad Especificada
Nuestra Dirección de remitente será la cuenta conectada por defecto. Para la dirección del destinatario y la cantidad especificada, generaremos un formulario con dos campos de entrada y un botón “send” que iniciará la transferencia.
Index.html
Inserta el formulario debajo del comentario .
<!-- Send Transaction -->
<form>
<div class="inputcontainer">
<input
id="addressinput"
class="myinput"
placeholder="Address 0x0..."
/>
<input
id="amountinput"
class="myinput"
placeholder="Amount ether..."
/>
</div>
<div class="buttoncontainer">
<button type="button" id="sendButton" class="button64">Send</button>
</div>
</form>
Main.js
Para activar la Funcionalidad de Enviar Transacción, necesitamos crear dos funciones principales.
- Event Listener para el Botón SendTransaction
- Tras un evento de clic, verifica si MetaMask está disponible y conectado.
- En caso afirmativo, llama a la función SendFunction().
- De lo contrario, registra un error y actualiza el estado de la página web.
- SendFunction()
- Esta función es responsable de enviar la transacción.
- Recupera la dirección del destinatario y la cantidad especificada mediante Manipulación del DOM.
- Adicionalmente, crea un objeto de javascript con los detalles de la transacción; from, to, amount; dentro de transaction.
- Envía una transacción en la red Ethereum con los detalles de transacción proporcionados, transaction, a través de web3.eth.sendTransaction(transaction)
// Event Listener for Send Transaction
document.getElementById("sendButton").addEventListener("click", async () => {
const metaMaskAvailable = await checkMetaMaskAvailability();
if (metaMaskAvailable) {
await SendFunction();
}
});
//Function to call the Send Function
async function SendFunction() {
// Get input values
const to = document.getElementById("addressinput").value;
const amount = document.getElementById("amountinput").value;
// Check if both to and amount are provided
if (!to || !amount) {
console.error("To and amount are required");
return;
}
// Convert amount to wei (1 ether = 10^18 wei)
const amountWei = web3.utils.toWei(amount, "ether");
// Get the selected account from MetaMask
const accounts = await web3.eth.getAccounts();
const from = accounts[0];
// Create the transaction object
const transaction = {
from: from,
to: to,
value: amountWei,
};
// Send the transaction
try {
const result = await web3.eth.sendTransaction(transaction);
console.log("Transaction result:", result);
// Update status
document.getElementById("status2").innerText ="Transaction sent successfully";
document.getElementById("status2").style.color = "green";
} catch (err) {
// Handle error
console.error("Failed to send transaction:", err);// Update status
document.getElementById("status2").innerText = "Failed to send transaction";
document.getElementById("status2").style.color = "red";
}
}
Fragmentos de Código Importantes: Enviar Transacción
web3.js Send Transaction
await web3.eth.sendTransaction(transaction)
sendTransaction toma un único parámetro, transaction. Arroja un error si la transacción no tiene éxito.
transaction es un objeto que contiene los detalles de la transacción que se va a enviar. Este es el formato:
{
from: "Sender Address",
to: "Recepient Address",
value: "Amount to be sent in WEI",
};
Tu sitio web debería verse así:

Parte 4: Interactuar con un Smart Contract
En esta última sección, aprenderás cómo interactuar con un smart contract utilizando el objeto web3.eth.Contract. Esto incluye leer datos, escribir datos y manejar eventos.
- Lectura de Datos: Utiliza los métodos de lectura del contrato para obtener datos de este sin modificar el estado del contrato y generalmente su ejecución es gratuita.
- Escritura de Datos: Métodos que modifican el estado del contrato o realizan acciones mediante el envío de transacciones a la blockchain que pueden requerir tarifas de gas.
- Manejo de Eventos: Los smart contracts pueden emitir eventos durante su ejecución. Podemos escuchar estos eventos para recibir notificaciones cuando ocurren acciones específicas en el contrato.
Aquí tenemos un contrato con el que interactuarás:
// Rareskills contractpragma solidity ^0.8.0;contract RareSkills {
mapping(address => uint256) public balances;
uint256 public totalSupply;
event Mint(address indexed to, uint256 amount);
function mint(uint256 amount) public {
balances[msg.sender] += amount;
totalSupply += amount;
emit Mint(msg.sender, amount);
}
}
El contrato está desplegado en la red Mumbai de Polygon. Puedes consultarlo en el siguiente enlace: https://mumbai.polygonscan.com/
Index.html
Primero inserta el botón “mint” debajo del comentario.
<!-- Minting NFT -->
<div class="mintcontainer">
<button id="mintactual" class="button49">Mint</button>
<p id="demo3"></p>
</div>
Main.js
En web3.js primero tenemos que instanciar el contrato para poder interactuar con él. Hay dos elementos centrales para instanciar un contrato:
- contract address: 0x88d099496C1A493A36E678062f259FE9919B9150
- contract ABI: Encuéntralo aquí
Nuestro javascript tendrá dos funciones principales:
- Event Listener para nuestro Botón Mint
- Tras un evento de clic, verifica si MetaMask está disponible y conectado.
- En caso afirmativo, llama a la función mintNFT().
- De lo contrario, registra un error y actualiza el estado de la página web.
- mintNFT()
- Esta función es responsable de interactuar con el contrato de RareSkills.
- Crea una instancia del contrato utilizando el objeto web3.eth.Contract, pasando contractABI y contractAddress como sus argumentos.
- Recupera el suministro total (total supply) del contrato leyendo la función totalSupply.
- Mintea los datos del contrato ejecutando la función mint(uint256 amount).
- Escucha la ocurrencia del “evento Mint” y lo maneja.
Profundizaremos en cada uno de los detalles en los fragmentos de código.
// Event Listener for Mint Button
document.getElementById("mintbutton").addEventListener("click", async () => {
const metaMaskAvailable = await checkMetaMaskAvailability();
if (metaMaskAvailable) {
await mintNFT();
}
});
// Contract Details
const contractAddress = "0x88d099496C1A493A36E678062f259FE9919B9150"; // Hardcoded contract address
const contractABI = [
// Hard coded ABI
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "address",
name: "to",
type: "address",
},
{
indexed: false,
internalType: "uint256",
name: "amount",
type: "uint256",
},
],
name: "Mint",
type: "event",
},
{
inputs: [
{
internalType: "address",
name: "",
type: "address",
},
],
name: "balances",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256",
},
],
stateMutability: "view",
type: "function",
},
{
inputs: [
{
internalType: "uint256",
name: "amount",
type: "uint256",
},],name: "mint",outputs: [],stateMutability: "nonpayable",type: "function",},{inputs: [],name: "totalSupply",outputs: [{internalType: "uint256",name: "",type: "uint256",},],stateMutability: "view",type: "function",},];
// Funciton to mint
async function mintNFT() {
// Get connected account
const accounts = await web3.eth.getAccounts();
const from = accounts[0];
// Instantiate a new Contract
const contract = new web3.eth.Contract(contractABI, contractAddress);
try {
// Invoke contract methods
const result = await contract.methods.mint(1).send({ from: from , value: 0});
const _totalSupply = await contract.methods.totalSupply().call();
document.getElementById("status2").innerText = "TotalSupply: " + _totalSupply;
document.getElementById("status2").style.color = "green";
document.getElementById("status3").innerText = "Minting successful";
document.getElementById("status3").style.color = "green";
// Event Listener
contract
.getPastEvents("Mint", {
fromBlock: "latest", // Start from the latest block
})
.then((results) => console.log(results));
} catch (err) {
console.error("Failed to mint:", err);
document.getElementById("status3").innerText = "Failed to mint";
document.getElementById("status3").style.color = "red";
}
}
Fragmentos de Código Importantes
web3.js Contract
const contract = new web3.eth.Contract(contractABI, contractAddress);
Hemos instanciado una nueva instancia del contrato de RareSkills utilizando el constructor web3.eth.Contract, pasando contractABI y contractAddress como sus argumentos. Esta instancia nos permite interactuar directamente con el smart contract ubicado en contractAddress utilizando la interfaz definida en contractABI. Interactuar con el smart contract requiere que invoquemos la función .send() o .call() dependiendo de si se trata de una función de visualización de estado (state-viewing) o de cambio de estado (state-changing).
web3.js .send()
contract.methods.mint(1).send({ from: from , value: 0});
El método send() se utiliza al ejecutar funciones que alteran el estado del contrato. Dado que nuestra función mint se suma al totalSupply de nuestro contrato, es una función de cambio de estado. El objeto pasado al método send() { from: from, value: 0 } especifica los detalles de la transacción.
- from: indica la dirección desde la cual se envía la transacción.
- value: indica la cantidad de Ether que se envía junto con la transacción. En este caso, no se envía ningún Ether.
web3.js .call()
contract.methods.totalSupply().call(); El método de contrato call() se utiliza al ejecutar funciones que NO alteran el estado del contrato. Puesto que la función totalSupplyl() es una función de tipo “view”, utiliza el método call().
web.3.js event Listeners()
contract
.getPastEvents("Mint", {fromBlock: "latest",}).then((results) => console.log(results));
getPastEvents es un método de manejo de eventos que se llama sobre el objeto contract para obtener el último evento emitido.
-
El primer argumento es el nombre del evento, en nuestro caso es el evento “Mint”.
-
El segundo argumento es un objeto de opciones. En este caso, fromBlock se establece en “latest” para obtener eventos desde el último bloque disponible. Más información aquí.
El array results se registra en la consola y debería verse de esta manera:

Resultado Final del Sitio Web:

¡Felicidades por terminar este tutorial de web3.js!
Publicado originalmente el 26 de mayo de 2023