WEB3DEV

Cover image for Transferência de Tokens Sol Entre Contas - Ledger
Panegali
Panegali

Posted on • Atualizado em

Transferência de Tokens Sol Entre Contas - Ledger

Introdução

Nesta seção, vamos orientá-lo através da criação de um aplicativo. Este aplicativo criará uma transação que será assinada com a Ledger Nano antes de enviá-la para a blockchain. O objetivo do aplicativo é transferir sol (tokens) da sua conta Solana na sua Ledger para outra conta.

Pré-requisitos

Antes de iniciar, certifique-se de ter cumprido os pré requisitos.

Instale o aplicativo Solana Nano

Primeiro, você precisa instalar o aplicativo Solana Nano da Ledger Live, conforme indicado nos pré requisitos da Ethereum.

Implementação do tutorial

Nesta implementação, estaremos construindo uma aplicação web com uma linguagem javascript bem simples que usa o protocolo USB de um pacote Ledger para se comunicar com a ledger.

Inicialização do projeto

É hora de implementar o aplicativo e testá-lo. Primeiro, abra um terminal e crie uma nova pasta. Para este tutorial, a pasta terá o nome “e2e-sol-tutorial”. Execute:

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

Em seguida, inicialize o projeto executando o seguinte:

npm init
Enter fullscreen mode Exit fullscreen mode

Responda às perguntas exibidas ou, por padrão, pressione enter. Não há incidência na execução.

Execute:

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

Coloque este logotipo na pasta de ativos.

Sua pasta de trabalho deve ficar assim.
1 Fig. 2: Pasta do Aplicativo

Implementação de código

index.html

Em index.html, copie e cole o seguinte 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"></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>Clique no botão abaixo para conectar sua Carteira Ledger</p>
      <div class="d-flex flex-row w-100 justify-content-around">
        <button class="btn btn-primary w-25" data-bs-toggle="modal" data-bs-target="#WalletModal">Conecte sua carteira</button>
        <button class="btn btn-primary w-25" id="get-information">Obter informações</button>
      </div>
    </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">Chave Pública da Carteira</label>
            <input type="text" class="form-control" id="wallet" disabled>
          </div>
          <div class="col-md-12">
            <label for="recipient" class="form-label" disabled>Saldo</label>
            <input type="text" class="form-control" id="balance">
          </div>
          <div class="col-md-12">
            <label for="recipient" class="form-label">Beneficiário</label>
            <input type="text" class="form-control" id="recipient">
          </div>
          <div class="col-md-6">
            <label for="gasPrice" class="form-label">Preço do gas</label>
            <input type="text" class="form-control" id="gasPrice" disabled>
          </div>
          <div class="col-md-6">
            <label for="value" class="form-label">Valor</label>
            <input type="text" class="form-control" id="value" >
          </div>
          <div class="col-12">
            <button type="button" id="tx-transfer" class="btn btn-primary">Criar Transação</button>
          </div>
        </form>
      </div>
      <div class="w-50 d-flex flex-column">
            <p class="url">Solana explorer:</p>
            <a id="url" href="" target="_blank"></a>
      </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">Escolha a sua carteira</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

Em index.js, copie e cole o seguinte código:

import * as SolanaWeb3 de '@solana/web3.js';
import TransportWebUSB de "@ledgerhq/hw-transport-webusb";
import Solana de "@ledgerhq/hw-app-solana";
import { listen } de "@ledgerhq/logs";
import bs58 de "bs58";

//Provedor Infuria para a rede devnet Solana
const connection = new SolanaWeb3.Connection(SolanaWeb3.clusterApiUrl('devnet'),"confirmed");

let transport;
let _sol;
let addressWallet;
let recipient = SolanaWeb3.Keypair.generate().publicKey;
let value = 0.1;
let gasPrice;

//verificar todos os erros cometidos pelo Transport
listen(log => console.log(log));

document.getElementById("connect-ledger").onclick = async function () {
    //Conectando-se a Ledger Nano com protocolo USB
    transport = await TransportWebUSB.create();
}

document.getElementById("get-information").onclick = async function () {
    //Obter uma instância Solana e a chave pública da conta Ledger Nano solana
    _sol = new Solana(transport);
    const { address } = await _sol.getAddress("44'/501'/0'");
    addressWallet = new SolanaWeb3.PublicKey(bs58.encode(address));

    //Obtenha algumas propriedades do provedor
    const balance = await connection.getBalance(addressWallet);
    gasPrice = SolanaWeb3.LAMPORTS_PER_SOL / 100;

    //Preencher as entradas com o valor padrão
    document.getElementById("wallet").value = bs58.encode(address);
    document.getElementById("balance").value = balance/ SolanaWeb3.LAMPORTS_PER_SOL;
    document.getElementById("gasPrice").value = parseInt(gasPrice) + " wei";
    document.getElementById("value").value = value;
    document.getElementById("recipient").value = recipient.toBase58();
}


document.getElementById("tx-transfer").onclick = async function () {
    //Obtendo informações a partir das entradas
    recipient = new SolanaWeb3.PublicKey(document.getElementById("recipient").value);
    value = document.getElementById("value").value;

    //Construir transação com as informações coletadas
    try {
        const recentBlockhash = await connection.getRecentBlockhash();
        const transaction = new SolanaWeb3.Transaction({ feePayer: addressWallet, recentBlockhash: recentBlockhash.blockhash}).add(
            SolanaWeb3.SystemProgram.transfer({
                fromPubkey: addressWallet,
                toPubkey: recipient,
                lamports: SolanaWeb3.LAMPORTS_PER_SOL * value,
            }),
        );


        //Serializando a transação para passá-la à Ledger Nano para assinatura
        const unsignedTx = transaction.serializeMessage();

        //Assine com a Ledger Nano (Assine o que você vê)
        const { signature } = await _sol.signTransaction("44'/501'/0'", unsignedTx);
        transaction.addSignature(addressWallet,signature);

        //Serialize a mesma transação de antes, mas adicione a assinatura nela
        const signedTx = transaction.serialize();


        //Enviando a transação para a blockchain
        const hash = await connection.sendRawTransaction(signedTx, {preflightCommitment:"confirmed", skipPreflight: false});

        //Exibir a URL do explorador Solana na tela
        const url = "https://explorer.solana.com/tx/" + hash +"?cluster=devnet";
        document.getElementById("url").innerHTML = url;
        document.getElementById("url").href = url;
    } catch (error) {
        console.log(error);
    }
}
Enter fullscreen mode Exit fullscreen mode

style.css

Em style.css copie e cole o seguinte código:

.modal-content{
    width: 300px;
    height: 400px;
}

#conectar ledger{
    width: 17rem;
    height: 9rem;
    background-color: white;
    border: none;
}

#conectar 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

Instalação de dependências

Instale os pacotes

Execute:

npm install --save-dev parcel
npm install --save @ledgerhq/hw-app-solana
npm install --save @ledgerhq/hw-transport-webusb
npm install --save @ledgerhq/logs
npm install --save @solana/web3.js
npm install --save bs58
Enter fullscreen mode Exit fullscreen mode

Pacotes e o que eles fazem

parcel
É uma ferramenta de compilação que o ajudará a empacotar seu aplicativo para executá-lo no navegador.

@ledgerhq/hw-app-solana
Ele irá ajudá-lo a pedir a sua Ledger Nano para acessar o aplicativo solana na Ledger Nano.

@ledgerhq/hw-transport-webusb
Ele fornece todos os métodos para interagir com sua Ledger com uma conexão USB.

@ledgerhq/logs
Ele fornece o registro de todos os erros de sua conexão com seu dispositivo Ledger que podem aparecer durante o desenvolvimento.

@solana/web3.js
Ele fornece todos os métodos para interagir com a blockchain solana.

bs58
Ele fornece todos os métodos para calcular a codificação de base 58.

Modificar Package.json

Modifique a 5ª linha: "main": "index.js"=> "source": "index.html" E certifique-se de ter esta linha nos scripts:

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

Adicione isto no final do script:

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

Seu arquivo deve ficar assim:

{
    "name": "e2e-sol-tutorial",
    "version": "1.0.0",
    "description": "",
    "source": "index.html",
    "scripts": {
        "start": "parcel"
    },
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "parcel": "^2.3.2"
    },
    "dependencies": {
        "@ledgerhq/hw-app-solana": "^6.26.0",
        "@ledgerhq/hw-transport-webusb": "^6.24.1",
        "@ledgerhq/logs": "^6.10.0",
        "@solana/web3.js": "^1.36.0",
        "bs58": "^5.0.0"
    },
    "alias": {
        "@ledgerhq/devices": "@ledgerhq/devices/lib-es"
    }
}
Enter fullscreen mode Exit fullscreen mode

Teste do tutorial

Inicie o servidor de desenvolvimento

Agora que a configuração foi concluída, o aplicativo deve ser criado para ser exibido. Inicie o servidor de desenvolvimento:

npm run start

Enter fullscreen mode Exit fullscreen mode

Agora o aplicativo está funcionando. Abra o Chrome e vá para localhost:1234, ele exibirá:

2 Fig. 3: Aplicativo rodando no navegador

Conecte o seu dispositivo Ledger

Antes de clicar no texto, conecte sua Ledger à porta USB, desbloqueie-a e execute o aplicativo solana. As etapas são descritas abaixo.

3 Fig. 4: Digite o código PIN da Ledger

4 Fig. 5: Execute o aplicativo Solana na Ledger Nano

5 Fig. 6: O aplicativo Solana está sendo executado na Ledger Nano

Conecte sua Ledger ao aplicativo

Agora você pode clicar no botão “Connect your Wallet” e uma janela modal será aberta. Clique no logotipo da Ledger.

6 Fig. 7: Escolha da Carteira
Agora escolha a Ledger Nano para conectar ao navegador.

7 Fig. 8: Conecte a Ledger Nano

Após conectar a Nano, clique em “Get Information”. Se tudo correr bem, os campos de entrada serão preenchidos com dados. A entrada em cinza não deve ser alterada e é extraída diretamente da blockchain ou do seu aplicativo Ledger Nano.

8 Fig. 9: Aplicação após conectar a Ledger Nano

Envie o token Sol para sua conta solana Ledger Nano

Para enviar alguns tokens sol na rede Devnet, você pode ir a um dos sites de faucet solana ou fazê-lo com a interface de linha de comando da solana:

Faucet Solana
Solana CLI

Se você procura a maneira mais fácil e rápida, use o Faucet Solana. Se você preferir usar a CLI da Solana, leia esta documentação para instalá-la antes de começar a enviar Sol.

A Devnet da Solana não é visível na Ledger Live, você pode verificar a transação passada no Solana Explorer.

Opção n°1 - Faucet Solana
Vá para o site Faucet Solana coloque sua chave pública da carteira (exibida no aplicativo web) na entrada e clique em “Devnet”

9 Fig. 1: Faucet Solana

Opção nº 2 - Solana CLI

Vá para o site Solana CLI, existem etapas para adicionar alguns tokens sol à sua conta.

solana airdrop 1 <ENDEREÇO_DA_CONTA_DE_DESTINO> --url https://api.devnet.solana.com
Enter fullscreen mode Exit fullscreen mode

Por exemplo

solana airdrop 1 72tCcW6F4gRWJLCXf3RGejNDZBwUvWCfxHTdxoLGV4ht --url [https://api.devnet.solana.com](https://api.devnet.solana.com)
Enter fullscreen mode Exit fullscreen mode

Criar uma transação para transferir sol

Agora que as entradas estão preenchidas com dados, é hora de transferir alguns tokens sol da sua conta solana da Ledger para outra conta (você pode manter a conta padrão no arquivo “index.js”).

Portanto, clique em “Create Transaction” para criar a transação que será assinada pela sua Ledger antes de enviá-la para a blockchain.

10 Fig. 10: Aplicativo após conectar a Ledger Nano

Quando a transação prosseguir e finalizar, uma URL será exibida na tela. Esta URL é um link para o Solana Explorer para revisar a transação.

Lá você pode encontrar todas as informações sobre a transação que você enviou anteriormente.

11Fig. 11: URL de informações da transação

Se você for no Solana Explorer, poderá ver as informações de sua transação.

12 Fig. 12: Resultado no Solana Explorer após o envio da transação

13 Fig. 13: Resultado no Solana Explorer após o envio da transação

Parabéns, você construiu com sucesso seu primeiro aplicativo de transferência conectado à Ledger!!!


Este artigo foi publicado no Portal do desenvolvedor Ledger. Traduzido por Marcelo Panegali.

Top comments (0)