WEB3DEV Español

Delia Viloria T
Delia Viloria T

Posted on

Transferencia de Ethers entre cuentas - Ledger

Introducción

En esta sección, te guiaremos a través de la creación de una aplicación. Esta aplicación creará una transacción que se firmará con Ledger Nano antes de enviarla a blockchain. El objetivo de la aplicación es transferir ethers de tu cuenta Ethereum en tu Ledger a otra cuenta.

Requisitos previos

Antes de comenzar, asegúrate de cumplir con los pre-requisitos.

Envía el token Ether a tu cuenta Ethereum de Ledger Nano.

Para enviar algunos ethers en la red Ropsten, accede a uno de los sitios web de ropsten faucet:

La red Ropsten no es visible en Ledger Live, pero puedes comprobar la ejecución de la transacción en Ropsten.etherscan.io.

Si los faucets Ropsten y Dimension, no funcionan o la cola es demasiado larga, utiliza otra llave de tu preferencia para recibir el testnet Ether.

Red Ropsten Ethereum

Ve al sitio Ropsten Ethereum Faucet, coloca tu llave pública de la cartera en el campo y haz clic en “Send me test Ether”.
Image description
Fig. 1: Ropsten Ethereum Faucet

Red Dimension

Visita el sitio web de Dimensions Network coloca tu Llave Pública de la Cartera en la entrada, haz el captcha y luego clic en “Send me test Ether”
Image description
Fig. 2: Ropsten Ethereum Faucet

Implementación del tutorial

En esta implementación, estaremos construyendo una aplicación web con JavaScript vainilla que usa el protocolo HID de un paquete Ledger para comunicarse con ledger.

Inicialización del proyecto

Es hora de implementar la aplicación y probarla. Primero, abre un terminal y crea una nueva carpeta. Para este tutorial, la carpeta se llamará “e2e-Eth-tutorial”. Ejecuta:

mkdir e2e-eth-tutorial
cd e2e-eth-tutorial
Enter fullscreen mode Exit fullscreen mode

Inicializa el proyecto ejecutando lo siguiente:

npm init
Enter fullscreen mode Exit fullscreen mode

Responde a las preguntas que se muestran o de forma predeterminada, presiona enter. No hay incidencia en la ejecución.

Ejecuta:

touch index.html
touch index.js
touch style.css
mkdir assets
Enter fullscreen mode Exit fullscreen mode

Coloca este logotipo en la carpeta de activos.

Tu carpeta de trabajo debería verse así.
Image description
Fig. 3: Carpeta de la Aplicación

Implementación del código

index.html

En index.html, copia y pega el siguiente código:

<!DOCTYPE html>

<html>

  <head>

    <title>Parcel Sandbox</title>

    <meta charset="UTF-8" />

    <link rel="stylesheet" href="style.css">

    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>

    <script src="[https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js](https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js)"></script>

    <script type="module" src="index.js"></script>

  </head>

  <body class="m-5">

    <div class="d-flex flex-column justify-content-center m-5 align-items-center">

      <p>Click on the bellow button to connect your Ledger Wallet</p>

      <button class="btn btn-primary w-25" data-bs-toggle="modal" data-bs-target="#WalletModal">Connect your Wallet</button>

    </div>

    <div class="d-flex flex-row">

      <div id="app" class="w-50">

        <form class="row g-3">

          <div class="col-md-12">

            <label for="wallet" class="form-label">Wallet Public Key</label>

            <input type="text" class="form-control" id="wallet" disabled>

          </div>

          <div class="col-md-12">

            <label for="recipient" class="form-label">Recipient</label>

            <input type="text" class="form-control" id="recipient">

          </div>

          <div class="col-md-6">

            <label for="gasPrice" class="form-label">Gas Price in wei</label>

            <input type="text" class="form-control" id="gasPrice" disabled>

          </div>

          <div class="col-md-6">

            <label for="gasLimit" class="form-label">Gas Limit in wei</label>

            <input type="text" class="form-control" id="gasLimit">

          </div>

          <div class="col-md-6">

            <label for="chainId" class="form-label">Chain ID</label>

            <input type="text" class="form-control" id="chainId" disabled>

          </div>

          <div class="col-md-6">

            <label for="value" class="form-label">Value</label>

            <input type="text" class="form-control" id="value" >

          </div>

          <div class="col-12">

            <button type="button" id="tx-transfer" class="btn btn-primary">Create Transaction</button>

          </div>

        </form>

      </div>

      <div class="w-50 d-flex flex-column">

            <p class="url">Ropsten etherscan: </p>

            <p  id="url"></p>

      </div>

    </div>

    <!-- Modal -->

    <div class="modal fade" id="WalletModal" tabindex="-1" aria-labelledby="WalletModalLabel" aria-hidden="true">

      <div class="modal-dialog">

        <div class="modal-content">

          <div class="modal-header">

            <h5 class="modal-title" id="WalletModalLabel">Choose your Wallet</h5>

            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>

          </div>

          <div class="modal-body d-flex justify-content-center">

            <button id="connect-ledger" class="rounded-3 align-self-center" data-bs-dismiss="modal">

              <img src="./assets/ledger-logo.jpg" class="card-img-top" alt="Ledger">

            </button>

          </div>

        </div>

      </div>

    </div>

  </body>

</html>
Enter fullscreen mode Exit fullscreen mode

index.js

En index.js, copia y pega el siguiente código:

import { ethers } from "ethers";

import TransportWebHID from "@ledgerhq/hw-transport-webhid";

import Eth from "@ledgerhq/hw-app-eth";

//Provedor Infuria para a rede Ropsten 

const provider = new ethers.providers.JsonRpcProvider("https://ropsten.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161");

const chainId = 3;

let gasPrice;

let addressWallet;

let recipient = "0x920f19c7F7Ce5b3170AdB94fDcC4570Da95D286b";

let value = 0.1;

let gasLimit = 1000000;

let nonce;

let _eth;

document.getElementById("connect-ledger").onclick = async function () {

    //Conectando-se a Ledger Nano com o protocolo HID

    const transport = await TransportWebHID.create();

//Definindo uma instância Ethereum e obtendo a chave pública da conta Ledger Nano ethereum

    _eth = new Eth(transport);

    const { address } = await _eth.getAddress("44'/60'/0'/0/0", false);

    //Obtendo algumas propriedades do provedor

    addressWallet = address;

    gasPrice = (await provider.getGasPrice())._hex;

    gasPrice = parseInt(gasPrice,16) * 1.15;

    //Preenchendo as entradas com o valor padrão

    document.getElementById("wallet").value = address;

    document.getElementById("gasPrice").value = parseInt(gasPrice) + " wei";

    document.getElementById("chainId").value = chainId;

    document.getElementById("value").value = value;

    document.getElementById("recipient").value = recipient;

    document.getElementById("gasLimit").value = gasLimit;

}
document.getElementById("tx-transfer").onclick = async function () {

    //Obtendo informações das entradas

    addressWallet = document.getElementById("wallet").value;

    recipient =  document.getElementById("recipient").value;

    value =  document.getElementById("value").value;

    gasLimit =  parseInt(document.getElementById("gasLimit").value);

    nonce =  await provider.getTransactionCount(addressWallet, "latest");

    //Construindo a transação com as informações coletadas

    const transaction = {

        to: recipient,

        gasPrice: "0x" + parseInt(gasPrice).toString(16),

        gasLimit: ethers.utils.hexlify(gasLimit),

        nonce: nonce,

        chainId: chainId,

        data: "0x00",

        value: ethers.utils.parseUnits(value, "ether")._hex,

    }

    //Serializando a transação para passá-la a Ledger Nano para a assinatura

    let unsignedTx = ethers.utils.serializeTransaction(transaction).substring(2);

    //Assinando com a Ledger Nano (Assine o que você vê)

    const signature = await _eth.signTransaction("44'/60'/0'/0/0",unsignedTx);

    //Analisando a assinatura

    signature.r = "0x"+signature.r;

    signature.s = "0x"+signature.s;

    signature.v = parseInt(signature.v);

    signature.from = addressWallet;

    //dispondo em séria a mesma transação de antes, mas adicionando a assinatura nela

    let signedTx = ethers.utils.serializeTransaction(transaction, signature);

    //Enviando a transação para a blockchain

    const hash = (await provider.sendTransaction(signedTx)).hash;

    //Exibindo o Ropsten etherscan na tela

    const url = "https://ropsten.etherscan.io/tx/" + hash;

    document.getElementById("url").innerHTML
Enter fullscreen mode Exit fullscreen mode

style.css

En style.css copia y pega el siguiente código:


    width: 300px;

    height: 400px;

}

#connect-ledger{

    width: 17rem;

    height: 9rem;

    background-color: white;

    border: none;

}

#connect-ledger:hover{

    background-color: #EDEFF3;

}

.modal-body{

    background-color: #F7F9FD;

}

#url,.url{

    text-align: center;

    margin-top: 160px;

    color: green;

}`

Enter fullscreen mode Exit fullscreen mode

Instalación de dependencias

Instala los paquetes

Ejecuta:

npm install --save-dev parcel

npm install --save @ledgerhq/hw-app-eth

npm install --save @ledgerhq/hw-transport-webhid

npm install --save ethers
Enter fullscreen mode Exit fullscreen mode
Paquete ¿Qué hace?
parcel Es una herramienta de compilación que te ayudará a empaquetar tu aplicación para ejecutarla en el navegador.
.@ledgerhq/hw-app-eth Te ayudará a pedir a tu Ledger Nano que acceda a la dirección ethereum.
.@ledgerhq/hw-transport-webhid Proporciona todos los métodos para interactuar con tu Ledger con una conexión HID.
ethers Proporciona todos los métodos para interactuar con el blockchain ethereum.

Modificar Package.json

Modifica la 5a línea:

Image description

Y asegúrate de tener esta línea en los scripts:

 "scripts": {
    "start": "parcel"
  },
Enter fullscreen mode Exit fullscreen mode

Añade esto al final de script:

 "alias": {
    "@ledgerhq/devices": "@ledgerhq/devices/lib-es"
  }
Enter fullscreen mode Exit fullscreen mode

Tu archivo ahora debería verse así:

{

    "name": "e2e-eth-tutorial",

    "version": "1.0.0",

    "description": "",

    "source": "index.html",

    "scripts": {

      "start": "parcel"

    },

    "author": "",

    "license": "ISC",

    "devDependencies": {

      "parcel": "^2.3.2"

    },

    "dependencies": {

      "@ledgerhq/hw-app-eth": "^6.26.0",

      "@ledgerhq/hw-transport-webhid": "^6.24.1",

      "ethers": "^5.5.4"

    },

    "alias": {

      "@ledgerhq/devices": "@ledgerhq/devices/lib-es"

    }

}
Enter fullscreen mode Exit fullscreen mode

Prueba del tutorial

Inicia el servidor de desarrollo

Ahora que la configuración ha terminado, la aplicación debe compilarse para que se muestre. Inicia el servidor de desarrollo:
Image description

Ahora la aplicación está funcionando. Abre el navegador y dirígete a localhost:1234, se debe mostrar:

Fig. 5: Aplicación ejecutándose en el navegador

Image description

Conecta tu dispositivo de contabilidad

Antes de hacer clic en el texto, conecta tu Ledger al puerto USB, desbloquealo y ejecuta la aplicación ethereum. Las etapas son descritas abajo.

Image description

Fig. 6: En Ledger ingresa el código PIN

Image description

Fig. 7: Ejecuta la aplicación Ethereum en Ledger Nano

Image description

Fig. 8: La aplicación Ethereum está ejecutándose en Ledger Nano

Conecta tu Ledger a la aplicación

Ahora puedes hacer clic en el botón “Conectar tu cartera” y se abrirá una ventana emergente. Haz clic en el logotipo de Ledger.
Image description

Fig. 9: Elección de la cartera

Ahora elige Ledger Nano para conectarlo al navegador.
Image description

Fig. 10: Conexión de Ledger Nano

Si todo funciona bien, los campos de entrada se llenarán con los datos. La entrada en gris no debe cambiarse y se extrae directamente del blockchain o de tu aplicación Ledger Nano.
Image description

Fig. 11: Aplicación después de conectar a Ledger Nano

Crear una transacción para transferir ethereum

Ahora que las entradas están llenas de datos. Es hora de transferir algunos tokens ether de tu cuenta ethereum de Ledger a otra cuenta (puedes mantener la cuenta predeterminada en el archivo “index.js”).

Por lo tanto, haz clic en “Crear transacción” para crear la transacción que será firmada por tu Ledger antes de enviarla al blockchain.

Image description

Fig. 12: Aplicación después de conectar a Ledger Nano

Cuando la transacción continúe y termine, se mostrará una URL en la pantalla. Esta URL es un enlace a Ropsten Etherscan para revisar la transacción.

Allí puedes encontrar toda la información sobre la transacción que enviaste anteriormente.

Image description

Fig. 13: Resultado después del envío de la transacción

Si vas a Etherscan, podrás ver las informaciones de tu transacción.

Image description

Fig. 14: Informaciones de transacción en Ropsten Etherscan

¡Felicitaciones, construiste con éxito tu primera aplicación de transferencia conectada a Ledger!

Este artículo fue escrito por Ledger y traducido al español por Delia Viloria T.

El original en inglés puede ser encontrado aquí.
También puedes leerlo en portugués aquí.

Discussion (0)