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”.
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”
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
Inicializa el proyecto ejecutando lo siguiente:
npm init
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
Coloca este logotipo en la carpeta de activos.
Tu carpeta de trabajo debería verse así.
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>
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
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;
}`
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
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:
Y asegúrate de tener esta línea en los scripts:
"scripts": {
"start": "parcel"
},
Añade esto al final de script:
"alias": {
"@ledgerhq/devices": "@ledgerhq/devices/lib-es"
}
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"
}
}
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:
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
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.
Fig. 6: En Ledger ingresa el código PIN
Fig. 7: Ejecuta la aplicación Ethereum en Ledger Nano
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.
Fig. 9: Elección de la cartera
Ahora elige Ledger Nano para conectarlo al navegador.
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.
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.
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.
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.
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)