Configurar backend con Node.js y Hardhat

Introducción

En el ecosistema de desarrollo blockchain, Hardhat se ha consolidado como una de las herramientas más versátiles para la compilación, despliegue y prueba de contratos inteligentes sobre Ethereum. Integrarlo con un backend en Node.js permite crear aplicaciones descentralizadas (dApps) completas, donde la lógica off-chain y la interacción con la blockchain convergen de manera fluida.

Este artículo detalla, paso a paso, cómo configurar un proyecto backend en Node.js junto con Hardhat para desarrollar, testear y desplegar tus contratos inteligentes, siguiendo buenas prácticas y haciendo uso de Ethers.js como librería principal.

1. Pre-requisitos

  • Node.js v14 instalado. Descarga en nodejs.org.
  • npm o yarn como gestor de paquetes.
  • Conocimientos básicos de Solidity y JavaScript.
  • Cuenta en Infura o Alchemy para acceder a nodos de Ethereum (opcional para testnets/mainnet).

2. Instalación y configuración del proyecto

2.1 Inicializar el proyecto Node.js

En una carpeta vacía, ejecuta:

npm init -y

Esto crea un package.json con la configuración básica.

2.2 Instalar Hardhat y dependencias

Agrega Hardhat y Ethers.js al proyecto:

npm install --save-dev hardhat
npm install ethers @nomiclabs/hardhat-ethers dotenv express cors

También incluimos dotenv para variables de entorno y Express junto con CORS para el servidor.

2.3 Crear el entorno de Hardhat

Genera la configuración por defecto:

npx hardhat

Elige “Create a basic sample project” y confirma la instalación de dependencias sugeridas.

2.4 Configurar hardhat.config.js

require(dotenv).config()
require(@nomiclabs/hardhat-ethers)

module.exports = {
  solidity: 0.8.17,
  networks: {
    hardhat: {},
    ropsten: {
      url: process.env.ROPSTEN_URL,
      accounts: process.env.PRIVATE_KEY  [process.env.PRIVATE_KEY] : []
    }
  }
}

Define en un fichero .env tus variables:

Variable Descripción
ROPSTEN_URL Endpoint de nodo (Infura/Alchemy).
PRIVATE_KEY Clave privada de la cuenta desplegadora.

3. Desarrollo de contratos inteligentes

3.1 Crear un contrato de ejemplo

En contracts/Greeter.sol:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17

contract Greeter {
  string private greeting

  constructor(string memory _greeting) {
    greeting = _greeting
  }

  function greet() public view returns (string memory) {
    return greeting
  }

  function setGreeting(string memory _greeting) public {
    greeting = _greeting
  }
}

3.2 Compilar

Ejecuta:

npx hardhat compile

3.3 Pruebas unitarias

En test/greeter-test.js:

const { expect } = require(chai)

describe(Greeter, function () {
  it(should return the initial greeting, async function () {
    const Greeter = await ethers.getContractFactory(Greeter)
    const greeter = await Greeter.deploy(Hola Mundo)
    await greeter.deployed()

    expect(await greeter.greet()).to.equal(Hola Mundo)
  })
})

Lanza las pruebas con npx hardhat test.

4. Configuración del backend en Node.js

4.1 Estructura de carpetas

  • contracts/ – Contratos Solidity.
  • scripts/ – Despliegue de contratos con Hardhat.
  • test/ – Pruebas de contratos.
  • server/ – Código del backend Express.

4.2 Conexión a la blockchain con Ethers.js

En server/ethers.js:

require(dotenv).config()
const { ethers } = require(ethers)

const provider = new ethers.providers.JsonRpcProvider(process.env.ROPSTEN_URL)
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider)

// Exporta el proveedor y la wallet
module.exports = { provider, wallet }

4.3 Servidor Express y endpoints

En server/index.js:

const express = require(express)
const cors = require(cors)
const { wallet } = require(./ethers)
const GreeterArtifact = require(../artifacts/contracts/Greeter.sol/Greeter.json)

const app = express()
app.use(cors())
app.use(express.json())

const greeterAddress = DIRECCION_DEL_CONTRATO

app.get(/greet, async (req, res) => {
  const contract = new ethers.Contract(greeterAddress, GreeterArtifact.abi, wallet)
  const greeting = await contract.greet()
  res.json({ greeting })
})

app.post(/greet, async (req, res) => {
  const { message } = req.body
  const contract = new ethers.Contract(greeterAddress, GreeterArtifact.abi, wallet)
  const tx = await contract.setGreeting(message)
  await tx.wait()
  res.json({ txHash: tx.hash })
})

app.listen(3000, () => console.log(Servidor iniciado en puerto 3000))

5. Despliegue en testnet

  1. Configura scripts/deploy.js con tu contrato:
async function main() {
  const Greeter = await ethers.getContractFactory(Greeter)
  const greeter = await Greeter.deploy(Hola Testnet)
  await greeter.deployed()
  console.log(Greeter desplegado en:, greeter.address)
}

main().catch(console.error)
  1. Ejecuta: npx hardhat run --network ropsten scripts/deploy.js.
  2. Actualiza greeterAddress en tu backend con la dirección resultante.

6. Buenas prácticas y consejos

  • Seguridad: Nunca subas tus claves privadas en repositorios. Usa gestores de secretos.
  • Versionado: Bloquea las versiones de Solidity y dependencias.
  • Pruebas: Escribe casos extremos y prueba revert en fallos esperados.
  • Monitoreo: Integra herramientas como hardhat-gas-reporter.
  • Documentación: Mantén los scripts y variables bien documentadas en README.md.

Conclusión

Combinar Node.js y Hardhat ofrece una solución integral para el desarrollo de dApps robustas. Con esta configuración, cubres desde el diseño de contratos inteligentes hasta la exposición de APIs REST, facilitando la interacción off-chain. Aprovecha la flexibilidad de Hardhat, la potencia de Ethers.js y la simplicidad de Express para construir aplicaciones blockchain de alta calidad.

Para más detalles y actualizaciones, consulta la documentación oficial de Hardhat y Ethers.js.


Comentarios

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *