WEB3DEV

Cover image for Criando um Aplicativo Descentralizado de Votação com o Tutorial Choice Coin e Javascript Algorand SDK Usando NodeJs
Paulo Gio
Paulo Gio

Posted on • Atualizado em

Criando um Aplicativo Descentralizado de Votação com o Tutorial Choice Coin e Javascript Algorand SDK Usando NodeJs

https://algorand-developer-portal.tryprism.com/static/Posts/2022/01/25%2015:15/voting-js-sdk.jpeg?w=2220&cmd=resize_then_crop&height=1018&quality=70

Neste tutorial, você aprenderá como construir um aplicativo de votação com Choice Coin e JavaScript Algorand SDK usando NodeJs.

Requisitos

NPM e Node instalados, baixe AQUI

Uma chave de API Purestake: veja o tutorial

Contas de rede de teste financiadas: veja o tutorial

Um ambiente de desenvolvimento integrado (IDE), por exemplo, VSCode

Contexto

Este tutorial foi criado por Samuel Aspirin e Adetona Fashola.

Choice Coin é um Ativo Padrão da Algorand que potencializa o Decentralized Decisions; um software de votação e governança construído diretamente na blockchain Algorand. O software Decentralized Decisions permite que as organizações tomem decisões de governança de maneira aberta e descentralizada.

https://uploads.mwp.mprod.getusinfo.com/uploads/sites/29/2021/08/Screen-Shot-2021-08-16-at-5.37.50-AM.png

O objetivo da Choice Coin é permitir que organizações descentralizadas se governem e controlem ativos digitais de maneira equitativa. Mais organizações que desenvolvem projetos em Finanças Descentralizadas (DeFi), Tokens Não Fungíveis (NFTs) e redes blockchain precisam de uma maneira de governar. Ao contrário dos sistemas centralizados, que são inerentemente hierárquicos e piramidais por natureza, os sistemas descentralizados distribuem o poder e a tomada de decisões pelas redes globais de maneira justa. Assim, há necessidade de uma maneira de organizações descentralizadas poderem tomar decisões em livros-razão distribuídos.

Decentralized Decisions é um software projetado para atender a essa necessidade e fornecer um aplicativo de votação descentralizado pronto para uso usando Choice Coin na Rede Algorand.

O software Decentralized Decisions é de código aberto e está disponível no GitHub.

A principal linguagem de programação utilizada para o desenvolvimento do Decentralized Decisions é o Python, porém o software também pode ser escrito em outras linguagens, como o JavaScript.

Etapas:

  1. Configure a pasta do projeto e instale o algosdk
  2. Configure a API Purestake e crie um cliente
  3. Recupere a conta e insira o ID do ativo Choice Coin
  4. Escolhendo a Opção de Voto e Enviando o Voto
  5. Aguarde a confirmação para sincronizar o voto da Blockchain Algorand
  6. Verifique o saldo de $ Choice após a votação
  7. Execute o código completo

1. Configure a pasta do projeto e instale o algosdk

Crie uma nova pasta de projeto, isso pode ser feito no terminal com:

$ mkdir choice-coin-voting-app
Enter fullscreen mode Exit fullscreen mode

Depois de criar a pasta do projeto, digite o diretório no seu terminal

$ cd choice-coin-voting-app
Enter fullscreen mode Exit fullscreen mode

Para instalar dependências no projeto, você precisa iniciar uma instância NPM usando:

$ npm init -y
Enter fullscreen mode Exit fullscreen mode

Crie um novo arquivo, vou nomear o meu index.js. Isso também pode ser feito no terminal com:

$ touch index.js
Enter fullscreen mode Exit fullscreen mode

No terminal, com o npm, instale o AlgoSDK e o Prompt-Sync

$ npm install algosdk prompt-sync
Enter fullscreen mode Exit fullscreen mode

AlgoSDK é a biblioteca JavaScript oficial para comunicação com a rede Algorand. Ela é projetada para navegadores modernos e Node.js.

O módulo Prompt-Sync é uma função que cria funções de prompt, é a mesma coisa com o prompt dos navegadores, mas funciona com o ambiente NodeJS.

No arquivo index.js, importe os dois módulos.

const algosdk = require('algosdk'); 
const prompt = require('prompt-sync')(); 
Enter fullscreen mode Exit fullscreen mode

2. Configure a API Purestake e crie um cliente

Registre-se para uma conta de desenvolvedor Purestake e obtenha sua chave de API para interagir com a rede Algorand.

const server = "https://testnet-algorand.api.purestake.io/ps2";
const port = "";
const token = {
  "X-API-Key": "SUA CHAVE DE API", 
};
Enter fullscreen mode Exit fullscreen mode

Crie a constante AlgodClient para iniciar a conexão.

const algodClient = new algosdk.Algodv2(token, server, port)
Enter fullscreen mode Exit fullscreen mode

3. Recupere a conta e insira o ID do ativo Choice Coin

Crie um novo endereço de carteira testnet de myAlgoWallet ou Algosigner, copie e salve sua senha mnemônica de 25 e não compartilhe com ninguém.

Adicione fundos ao endereço da carteira com alguns ALGOs da testnet através da torneira.

Ative o ativo $Choice Coin com o ID 21364625 usando myAlgoWallet ou Algosigner

Troque os Algos da testnet por $choice no Tinyman.

Em index.js

const mnemonic = "Os 25 caracteres mnemônicos separados por um espaço em branco devem ser importados aqui"; 

const recoveredAccount = algosdk.mnemonicToSecretKey(mnemonic); 

const ASSET_ID = 21364625

const voting_address = "" 
Enter fullscreen mode Exit fullscreen mode

Na constante voting_address, insira uma carteira de endereço de votação recém-criada diferente daquela recuperada para a qual o valor de votação $choice pode ser enviado, certifique-se de que $choice está optando por receber votos como antes.

4. Escolhendo a Opção de Voto e Enviando o Voto

Crie uma função de votação e envie o valor votado de recoveredAccount para a carteira de voting_address dependendo da opção do candidato que está sendo votada.

const chooseVotingOption = async () => {
    const candidateOption = prompt("Pressione 0 para o candidato Zero ou Pressione 1 para o candidato Um:") 

     const amount = prompt("Insira o valor para se comprometer com a votação:");


    const params =  await algodClient.getTransactionParams().do()
    const encoder = new TextEncoder()

     if (!(candidateOption)) {
         console.log('Selecione uma opção de candidato válida');
     } else if (!Number(amount)) {
         console.log("Insira um valor de token de escolha válido para votar")
     }
      else  if (candidateOption == "0") {
            try {
                let txn = algosdk.makeAssetTransferTxnWithSuggestedParams(
                    recoveredAccount.addr,
                    voting_address,
                    undefined,
                    undefined,
                    Number(amount),
                    encoder.encode("Votação com Choice coin"),
                    ASSET_ID,
                    params

                )

        let signedTxn = txn.signTxn(recoveredAccount.sk);
        const response =  await algodClient.sendRawTransaction(signedTxn).do();
            if(response) {
              console.log(`Você acabou de votar no candidato Zero, seu ID de voto: ${response.txId}`);

                waitForConfirmation(algodClient, response.txId);
            } else {
                console.log('erro ao votar no candidato Zero, tente novamente mais tarde')
            }

        }
        catch(error) {
            console.log("erro ao votar no candidato Zero, tente novamente mais tarde");
        }

 } 


     else  if(candidateOption == "1"){
        try {
            let txn = algosdk.makeAssetTransferTxnWithSuggestedParams(
                recoveredAccount.addr,
                voting_address,
                undefined,
                undefined,
                Number(amount),
                encoder.encode("Votação com Choice coin"),
                ASSET_ID,
                params
            )
       let signedTxn = txn.signTxn(recoveredAccount.sk);
       const response =  await algodClient.sendRawTransaction(signedTxn).do();
            if(response) {
               console.log(`Você acabou de votar no candidato Um, seu ID de votação: ${response.txId}`);

                waitForConfirmation(algodClient, response.txId);
            } else {
               console.log('erro ao votar no candidato um, tente novamente mais tarde')
            }

        }
        catch(error) {
            console.log("Erro ao votar no candidato um, tente novamente mais tarde");
        }

        }
        }
Enter fullscreen mode Exit fullscreen mode

5. Aguarde a confirmação para sincronizar o voto da Blockchain Algorand

const waitForConfirmation = async function (algodClient, txId) {
    let lastround = (await algodClient.status().do())['last-round'];
     while (true) {
        const pendingInfo = await algodClient.pendingTransactionInformation(txId).do();
        if (pendingInfo['confirmed-round'] !== null && pendingInfo['confirmed-round'] > 0) {
          //Obteve a transação concluída
          console.log('Votação confirmada na rodada ' + pendingInfo['confirmed-round']);
          break;
        }
        lastround++;
        await algodClient.statusAfterBlock(lastround).do();
     }
 };
Enter fullscreen mode Exit fullscreen mode

Esta função verifica quando o voto está sendo confirmado a partir da rede Algorand.

6. Verifique o saldo de $ Choice após a votação

const checkBalance = async () => {

    // obter as informações da conta
    const accountInfo =  await algodClient.accountInformation(recoveredAccount.addr).do();
    const assets =  accountInfo["assets"];

    // obter a quantidade de choice dos ativos
    assets.map(asset => {
        if (asset['asset-id'] === ASSET_ID) {
            const amount = asset["amount"];
            const choiceAmount = amount / 100;
            console.log(
                `Conta ${recoveredAccount.addr} tem ${choiceAmount} $choice`
              );
              return;
        }  else {
            console.log(`Conta ${recoveredAccount.addr} deve optar pelo ID do ativo Choice Coin ${ASSET_ID}`);
          }
     })

  };
Enter fullscreen mode Exit fullscreen mode

Verifique o saldo de $Choice após o término da votação. Se não houver um ID do ativo Choice nas informações da conta, a função é interrompida usando return e uma mensagem do console é mostrada para adicionar o ID do ativo Choice ao endereço da carteira.

7. Execute o código completo

O index.js ficaria assim.

const algosdk = require('algosdk'); 
const prompt = require('prompt-sync')();  

// abra uma API Purestake e obtenha uma API KEY exclusiva
const server = "https://testnet-algorand.api.purestake.io/ps2";
const port = "";
const token = {
  "X-API-Key": "your API key", 
};
const algodClient = new algosdk.Algodv2(token, server, port); 

// crie uma conta na testnet com myalgowallet, guarde a chave mnemônica
const mnemonic = "Os 25 caracteres mnemônicos separados por um espaço em branco devem ser importados aqui";

// obter conta da chave mnemônica
const recoveredAccount = algosdk.mnemonicToSecretKey(mnemonic); 

// ID do ativo choice coin
const ASSET_ID = 21364625

const voting_address = "insira um endereço de carteira de votação para a qual você possa enviar Choice, certifique-se de que Choice esteja optando por receber votos"

// Digite 1 para votar no candidato um e 0 para votar no candidato Zero

const chooseVotingOption = async () => {
    const candidateOption = prompt("Pressione 0 para o candidato Zero ou Pressione 1 para o candidato Um:") 
     const amount = prompt("Insira o valor para se comprometer com a votação:");


    const params =  await algodClient.getTransactionParams().do(); 
    const encoder = new TextEncoder();  

    // se não houver opção válida
    if (!(candidateOption)) {
        console.log('Selecione uma opção de candidato válida');
    } else if (!Number(amount)) {
        console.log("Insira um valor de token Choice válido para votar")
    }
    else  if (candidateOption == "0") {
            try {
                let txn = algosdk.makeAssetTransferTxnWithSuggestedParams(
                    recoveredAccount.addr,
                    voting_address,
                    undefined,
                    undefined,
                    Number(amount),
                    encoder.encode("Votação com Choice coin"),
                    ASSET_ID,
                    params

                )

            let signedTxn = txn.signTxn(recoveredAccount.sk);
            const response =  await algodClient.sendRawTransaction(signedTxn).do();
            if(response) {
                console.log(`Você acabou de votar no candidato Zero, seu ID de voto: ${response.txId}`);
                <!-- wait for confirmation-->
                waitForConfirmation(algodClient, response.txId);
            } else {
                console.log('erro ao votar no candidato Zero, tente novamente mais tarde')
            }

        } catch(error) {
            console.log("erro ao votar no candidato Zero, tente novamente mais tarde");
        }

 } else  if(candidateOption == "1"){
    try {
        let txn = algosdk.makeAssetTransferTxnWithSuggestedParams(
            recoveredAccount.addr,
            voting_address,
            undefined,
            undefined,
            Number(amount),
            encoder.encode("Votação com Choice coin"),
            ASSET_ID,
            params
        )
        let signedTxn = txn.signTxn(recoveredAccount.sk);
        const response =  await algodClient.sendRawTransaction(signedTxn).do();
        if(response) {
            console.log(`Você acabou de votar no candidato Um, seu ID de votação: ${response.txId}`);
            <!-- wait for confirmation-->
            waitForConfirmation(algodClient, response.txId);
        } else {
            console.log('erro ao votar no candidato um, tente novamente mais tarde')
        }

    } catch(error) {
        console.log("Erro ao votar no candidato um, tente novamente mais tarde");
    }
    }
}

chooseVotingOption();

// função de verificação
const waitForConfirmation = async function (algodClient, txId) {
    let lastround = (await algodClient.status().do())['last-round'];
     while (true) {
        const pendingInfo = await algodClient.pendingTransactionInformation(txId).do();
        if (pendingInfo['confirmed-round'] !== null && pendingInfo['confirmed-round'] > 0) {
          console.log('Votação confirmada na rodada ' + pendingInfo['confirmed-round']);
          break;
        }
        lastround++;
        await algodClient.statusAfterBlock(lastround).do();
     }
 };


// verificar saldo da conta
const checkBalance = async () => {
    const accountInfo =  await algodClient.accountInformation(recoveredAccount.addr).do();
    const assets =  accountInfo["assets"];

    // obter a quantidade de Choice dos ativos
    assets.map(asset => {
        if (asset['asset-id'] === ASSET_ID) {
            const amount = asset["amount"];
            const choiceAmount = amount / 100;
            console.log(
                `Conta ${recoveredAccount.addr} tem ${choiceAmount} $choice`
              );
              return;
        }  else {
            console.log(`Conta ${recoveredAccount.addr} deve optar pelo ID do ativo Choice Coin ${ASSET_ID}`);
         }
    })
};

checkBalance();
Enter fullscreen mode Exit fullscreen mode

Para determinar o vencedor, você pode verificar a saída da função checkBalance que mostra o número de $choice que cada conta possui. Este número representa o número total de votos para cada opção. Se quiser, você pode escrever uma função rápida para determinar quem recebeu mais votos.

Em conclusão, fizemos uma aplicação de votação com Choice Coin e Javascript com o Algorand SDK usando NodeJS. Você pode conferir o código completo no GitHub

(Fonte da imagem: Unsplash @Arnaud Jaegers)

Tutorial original escrito por Samuel Aspirin, traduzido por Paulinho Giovannini.

Top comments (0)