Este tutorial está diseñado para guiar a quienes desean aprender más acerca de Web3. Es ideal para un nivel medio.
Web3 representa un cambio de paradigma hacia una Internet descentralizada, donde las aplicaciones (dApps) interactúan directamente con blockchains como Ethereum. Esta guía de nivel intermedio profundiza en la interacción programática con Contratos Inteligentes utilizando librerías como ethers.js o web3.js, cubriendo la lectura y escritura de datos en la blockchain. Explora la importancia del ABI (Application Binary Interface), el manejo de proveedores (Providers) y firmantes (Signers), la gestión de transacciones (incluyendo tarifas de gas, límites y estados), y la interacción con estándares de tokens comunes como ERC-20 y ERC-721. También aborda la conexión a diferentes redes, patrones de desarrollo frontend para dApps, el uso de proveedores de RPC (Infura, Alchemy) y consideraciones básicas de seguridad al construir o interactuar con dApps. Permite a los desarrolladores empezar a construir interfaces funcionales para aplicaciones descentralizadas.
Un 'Hola, mundo' en Web3: conectar a una red blockchain usando una billetera como MetaMask y obtener información básica de la cuenta activa, como su dirección y balance de ETH.
// Asumiendo que MetaMask está instalado e inyecta window.ethereum
async function connectAndGetBalance() {
if (typeof window.ethereum === 'undefined') {
console.log('MetaMask no detectado. Instálalo.');
return;
}
try {
// Solicitar acceso a la(s) cuenta(s)
const provider = new ethers.providers.Web3Provider(window.ethereum);
await provider.send('eth_requestAccounts', []);
// Obtener la cuenta activa y su Signer
const signer = provider.getSigner();
const address = await signer.getAddress();
console.log('Cuenta conectada:', address);
// Consultar balance de ETH
const balance = await provider.getBalance(address);
console.log('Balance ETH:', ethers.utils.formatEther(balance));
} catch (error) {
console.error('Error al conectar o obtener balance:', error);
}
}
connectAndGetBalance();
Resultado:
Cuenta conectada: 0x...
Balance ETH: 1.2345
Familiarizarse con estos comandos es esencial para interactuar eficientemente con Web3:
const provider = new ethers.providers.Web3Provider(window.ethereum);
// Para Ethereum Mainnet con Infura
const provider = new ethers.providers.InfuraProvider('mainnet', 'TU_INFURA_PROJECT_ID');
// Para Polygon Mainnet con Alchemy
const provider = new ethers.providers.AlchemyProvider('matic', 'TU_ALCHEMY_API_KEY');
const accounts = await provider.send('eth_requestAccounts', []);
const address = accounts[0]; // La primera cuenta es la activa
const signer = provider.getSigner();
const address = await signer.getAddress();
const balanceWei = await provider.getBalance(address);
console.log(ethers.utils.formatEther(balanceWei)); // Formatear de wei a ether
const contractAddress = '0x...'; // Dirección del contrato desplegado
const contractABI = [...]; // ABI del contrato en formato JSON (array)
const provider = new ethers.providers.Web3Provider(window.ethereum); // O cualquier otro Provider
const contract = new ethers.Contract(contractAddress, contractABI, provider);
const nombre = await contract.name(); // Llamar a una función 'name'
const simbolo = await contract.symbol(); // Llamar a una función 'symbol'
const balanceToken = await contract.balanceOf('0x...'); // Llamar a una función 'balanceOf' con argumento
const contractAddress = '0x...';
const contractABI = [...];
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner(); // Obtener el Signer de la cuenta conectada
const contractWithSigner = new ethers.Contract(contractAddress, contractABI, signer);
// Asumiendo que 'contractWithSigner' ya está inicializado con un Signer
const txResponse = await contractWithSigner.mintNFT('direccion_destinatario', 'token_uri'); // Llamar a una función 'mintNFT'
console.log('Hash de transacción:', txResponse.hash);
// Opcional: Esperar a que la transacción se confirme
const receipt = await txResponse.wait();
console.log('Transacción confirmada en el bloque:', receipt.blockNumber);
// Asumiendo que 'tokenContractWithSigner' ya está inicializado con un Signer para el token
const recipientAddress = '0x...';
const amountToSend = ethers.utils.parseUnits('50', 'ether'); // Enviar 50 tokens (asumiendo 18 decimales)
const txResponse = await tokenContractWithSigner.transfer(recipientAddress, amountToSend);
await txResponse.wait();
// Asumiendo 'tokenContractWithSigner' con Signer para el token
const spenderAddress = '0x...'; // Dirección del contrato o cuenta que se le da permiso
const amountToApprove = ethers.utils.parseUnits('100', 'ether'); // Aprobar que gaste 100 tokens
const txResponse = await tokenContractWithSigner.approve(spenderAddress, amountToApprove);
await txResponse.wait();
// Asumiendo 'nftContractWithSigner' con Signer para el contrato NFT
const fromAddress = await signer.getAddress(); // Tu dirección
const toAddress = '0x...'; // Dirección del nuevo propietario
const tokenId = 123; // ID del NFT a transferir
const txResponse = await nftContractWithSigner.transferFrom(fromAddress, toAddress, tokenId);
await txResponse.wait();
// Asumiendo 'contractWithSigner' con Signer para el contrato
const gasLimitEstimate = await contractWithSigner.estimateGas.someStateChangingFunction(arg1, arg2);
// Asumiendo 'contract' inicializado con un Provider
contract.on('Transfer', (from, to, amount, event) => {
console.log(`Evento Transfer: De ${from} a ${to}, Cantidad: ${ethers.utils.formatEther(amount)}`);
// event.log, event.getBlock(), etc. para más detalles
});
// Dejar de escuchar eventos
// contract.off('Transfer');
Comprender estos conceptos fundamentales te ayudará a dominar Web3 de forma más organizada y eficiente:
Proveedores (Providers) y Firmantes (Signers):
Comprender que un 'Provider' es una conexión a la red blockchain que te permite leer datos (consultar saldos, ver el estado de contratos), pero no modificarlo. Un 'Signer' (generalmente asociado a una cuenta en una billetera como MetaMask) puede firmar transacciones para modificar el estado de la blockchain. Necesitas un Provider para interactuar, y un Signer además para escribir.
Contratos Inteligentes (Smart Contracts) e Interacción:
Programas auto-ejecutables que residen en la blockchain. Puedes interactuar con ellos de dos formas principales: 'Lectura' (llamar funciones `view` o `pure` para obtener información, no cuesta gas) y 'Escritura' (enviar transacciones para ejecutar funciones que modifican el estado, requiere gas y firma).
ABI (Application Binary Interface):
Un documento (típicamente JSON) que define la interfaz de un contrato inteligente. Especifica qué funciones y eventos tiene el contrato, cómo llamarlos, qué argumentos esperan y qué tipo de datos devuelven/emiten. Las librerías Web3 (ethers.js, web3.js) necesitan el ABI y la dirección del contrato para interactuar con él.
Transacciones Blockchain Avanzado (Gas, Nonce, Ciclo de Vida):
Profundizar en los detalles técnicos de las transacciones: qué son las tarifas de gas (costo de computación), el 'Gas Price' (precio por unidad de gas, afecta la velocidad), el 'Gas Limit' (cantidad máxima de gas para la ejecución), el 'Nonce' (contador de transacciones por cuenta) para asegurar el orden. Entender el ciclo de vida de una transacción (creada, firmada, enviada, pendiente, incluida en un bloque, confirmada/fallida).
Estándares de Tokens (ERC-20, ERC-721) Programáticamente:
Saber cómo interactuar con contratos que implementan los estándares de tokens más comunes desde tu código. Para ERC-20 (tokens fungibles): llamar métodos como `balanceOf`, `transfer`, y crucialmente `approve` (permitir que otro contrato gaste tus tokens). Para ERC-721 (NFTs): `ownerOf`, `transferFrom`, `approve`.
Conexión a Diferentes Redes y Proveedores RPC:
Configurar tu aplicación para conectarse a varias redes blockchain (Ethereum Mainnet, testnets, Layer 2s como Polygon o Arbitrum, u otras cadenas EVM). Utilizar proveedores RPC (Infura, Alchemy, QuickNode) para obtener acceso fiable a los nodos de la red, especialmente para backends o aplicaciones que no dependen de una billetera de navegador.
Patrones de Desarrollo Frontend para dApps:
Estructurar tu código frontend para detectar y conectar con billeteras Web3 (usando la interfaz `window.ethereum`), solicitar acceso a las cuentas, manejar cambios de red o cuenta, y guiar al usuario a través de las solicitudes de firma de mensajes y transacciones de forma intuitiva.
Estimación de Gas:
Utilizar las funciones de las librerías Web3 para estimar la cantidad de gas que una llamada a una función de contrato consumirá ANTES de que el usuario firme la transacción. Esto permite mostrarle una estimación del costo y mejorar la experiencia de usuario.
Eventos de Contratos Inteligentes:
Comprender cómo los contratos inteligentes pueden 'emitir' eventos para señalar que algo ha ocurrido en la blockchain. Aprender a escuchar estos eventos desde tu aplicación para reaccionar a cambios en tiempo real (ej: actualizar la UI cuando se transfiere un token o se crea un nuevo NFT).
Consideraciones de Seguridad en el Desarrollo de dApps:
Ser consciente de los riesgos tanto para los usuarios como para la aplicación. Validar entradas del usuario antes de interactuar con contratos, entender los permisos que tu dApp solicita a la billetera, proteger claves privadas (si gestionas cuentas de servicio en backend), y educar a los usuarios sobre lo que están firmando. Auditar contratos inteligentes.
Algunos ejemplos de aplicaciones prácticas donde se utiliza Web3:
Construir la interfaz de usuario (frontend) para dApps que interactúan con contratos inteligentes personalizados:
Desarrollar aplicaciones web que se conectan a la blockchain, leen datos (ej: estado de un juego, información de un perfil) y permiten al usuario realizar acciones que modifican el estado (ej: enviar un mensaje, cambiar un parámetro).
Integrar funcionalidades de transferencia y gestión de tokens ERC-20 en una aplicación:
Permitir a los usuarios ver sus saldos de tokens, enviar tokens a otras direcciones, y aprobar que otros contratos (ej: un exchange descentralizado) puedan gastar sus tokens en su nombre.
Integrar funcionalidades de visualización, compra/venta y transferencia de NFTs (ERC-721):
Desarrollar marketplaces o galerías de NFTs donde los usuarios pueden ver sus colecciones, poner NFTs a la venta, comprarlos y transferirlos utilizando su billetera Web3.
Desarrollar aplicaciones que interactúan con protocolos de Finanzas Descentralizadas (DeFi):
Construir interfaces para plataformas de lending/borrowing, intercambios descentralizados (DEXs), protocolos de staking o yield farming, permitiendo a los usuarios interactuar con los contratos inteligentes de estos protocolos para gestionar sus activos financieros.
Implementar flujos de usuario que requieran la firma de mensajes para autenticación o la firma de transacciones para acciones en la blockchain:
Guiar al usuario a través del proceso de conexión de billetera, solicitar firmas para demostrar posesión de una cuenta (sin coste de gas) o para ejecutar operaciones que modifican el estado y requieren pago de gas.
Desarrollar backends o servicios que leen datos de la blockchain o envían transacciones programáticamente:
Construir servicios que utilicen proveedores RPC (Infura, Alchemy) para monitorizar la blockchain, consultar información (ej: el estado de un contrato, los últimos eventos) o enviar transacciones (ej: acuñar NFTs automáticamente, ejecutar ciertas operaciones de contratos).
Manejar el estado de las transacciones y proporcionar feedback al usuario:
Desarrollar la lógica frontend para seguir el ciclo de vida de una transacción después de que el usuario la firme en MetaMask (pendiente, confirmada, fallida) y actualizar la interfaz de usuario en consecuencia.
Configurar la aplicación para conectarse a diferentes redes blockchain y manejar el cambio de red:
Permitir que los usuarios seleccionen la red con la que quieren interactuar y asegurarse de que la aplicación se conecte correctamente a esa red utilizando el proveedor RPC o la billetera configurada.
Aquí tienes algunas recomendaciones para facilitar tus inicios en Web3:
Entiende el Papel del ABI (Application Binary Interface):
El ABI es crucial para interactuar con contratos inteligentes. Piensa en él como el manual de instrucciones del contrato. Necesitas el ABI correcto (generalmente un archivo JSON) y la dirección del contrato para que tu código Web3 pueda 'hablar' con él, llamando a sus funciones y entendiendo sus eventos.
Practica la Interacción con Contratos: Lectura y Escritura:
Comienza con contratos simples desplegados en testnets (usando ETH de prueba). Practica llamar funciones que solo leen datos (`view`, `pure`) – no cuestan gas. Luego, practica enviar transacciones que cambian el estado – estas sí cuestan gas y requieren que el usuario firme en su billetera. Familiarízate con las solicitudes de firma en MetaMask.
Aprende a Manejar las Tarifas de Gas y la Estimación de Gas:
Entiende que las operaciones que modifican la blockchain cuestan 'gas'. Aprende a usar las funciones de estimación de gas de tu librería Web3 (ej: `contract.estimateGas.myFunction(...)`) para darle al usuario una idea del costo antes de que firme la transacción. Familiarízate con cómo el 'Gas Price' afecta la velocidad de confirmación.
Utiliza Exploradores de Bloques (Etherscan, etc.) para Depurar:
Los exploradores de bloques son tus mejores amigos al desarrollar dApps. Si una transacción falla o no hace lo que esperas, busca el hash de la transacción en Etherscan (o el explorador de la red correspondiente). Podrás ver los detalles del error, el gas usado, los eventos emitidos y el estado real en la blockchain.
Implementa la Conexión de Billetera Correctamente y Maneja Cambios:
Sigue el patrón recomendado para detectar `window.ethereum` (inyectado por MetaMask y otras billeteras), solicitar la conexión de cuentas y escuchar eventos (`on('accountsChanged')`, `on('chainChanged')`) para reaccionar si el usuario cambia de cuenta o de red.
Sé Consciente de la Seguridad: Valida Entradas y Entiende Firmas/Aprobaciones:
Valida siempre las entradas que vienen de los usuarios en tu frontend antes de usarlas en llamadas a contratos. Entiende qué significa que un usuario firme un mensaje vs. firmar una transacción (la segunda modifica la blockchain y cuesta gas). Sé extremadamente cuidadoso con las solicitudes de 'Aprobación' (Approve) de tokens – asegúrate de que el usuario entienda a quién y por cuánto da permiso.
Elige un Proveedor RPC Confiable:
Para que tu aplicación se conecte a la blockchain, necesitas un proveedor RPC (RPC Provider). Puedes usar `window.ethereum` (la billetera del usuario) o servicios de nodos alojados como Infura, Alchemy o QuickNode (especialmente para backends o si no usas billetera en frontend). Elije uno fiable con buen rendimiento y plan adecuado.
Familiarízate con los Estándares de Tokens (ERC-20, ERC-721):
Si tu dApp interactúa con tokens (transferencias, saldos, NFTs), es crucial entender los métodos estándar definidos en ERC-20 y ERC-721. Las librerías Web3 tienen helpers para interactuar fácilmente con estos contratos estándar.
Maneja los Estados de las Transacciones en la UI:
Las transacciones blockchain no son instantáneas. Después de que el usuario firme, la transacción pasa por estados (pendiente, confirmada, fallida). Tu interfaz de usuario debe reflejar estos estados (ej: mostrar un spinner mientras está pendiente) y dar feedback al usuario cuando se confirma o falla.
Si te interesa Web3, también podrías explorar estas herramientas:
Amplía tus conocimientos con estos enlaces y materiales: