WEB3DEV

Cover image for Aplicativo Serverless Algorand no AWS Lambda - Algorand
Arnaldo Pereira Campos Junior
Arnaldo Pereira Campos Junior

Posted on • Atualizado em

Aplicativo Serverless Algorand no AWS Lambda - Algorand

Neste tutorial, você aprenderá a desenvolver, implantar e testar um aplicativo Java serverless simples no AWS Lambda.

O aplicativo executa duas tarefas diretas na blockchain Algorand:

Recuperar a quantidade total de Algos de uma Conta
Enviar Algos entre contas

No entanto, pode ser usado como modelo para desenvolver soluções mais complexas. No final do tutorial, você poderá criar um aplicativo Java completo, implantar no AWS Lambda e testá-lo.

Image descriptionDavid Ciamberlano

12 de janeiro de 2022
Java

Requisitos

Para seguir este tutorial, você precisará do JDK 11+, Maven 3.6+ e um IDE Java, por exemplo, VS Code studio ou IntelliJ (usado por mim).

Para implantar e testar o aplicativo serverless, você precisa de uma conta da AWS. Você pode facilmente criar um no AWS Lambda. Você será solicitado a fornecer informações de cartão de crédito/débito, número de telefone e endereço.

Este serviço está qualificado para o nível gratuito do AWS Lambda, incluindo um milhão de solicitações gratuitas e 400.000 GB-segundos de computação por mês. Assim, você não será cobrado por seus testes (a menos que faça milhões de chamadas…).

Mesmo que a solução seja fácil de seguir, vale a pena ter uma experiência básica com Java. Além disso, você precisará importar várias fontes para o pom.xml, onde uma delas é Algorand Java SDK

Background

Um aplicativo serverless é um serviço de computação que permite executar código sem provisionar ou gerenciar servidores. Você precisa de administração zero para poder se concentrar no software em vez do gerenciamento de infraestrutura e permitir que a AWS mantenha e dimensione o servidor para você.

Usando o AWS Lambda, você paga apenas pelo tempo de computação que consumir e não será cobrado enquanto seu código não estiver em execução.

Etapas a seguir

1. Dependências e configurações iniciais

Observação: você pode encontrar o projeto completo no GitHub na URL: GitHub - david-ciamberlano/algo-serverless: Base project for Algorand on AWS lambda .

Você pode começar com um projeto padrão Maven. As instruções de compilação podem diferir com base em seu sistema operacional e IDE. No Linux, se você instalou com sucesso o Maven e o Java, pode criar facilmente um projeto de amostra usando um comando semelhante: mvn archetype:generate -DgroupId=com.mytest.app -DartifactId=my-app -DarchetypeVersion=1.4 -DinteractiveMode=false

No pom.xml em <dependecies>, primeiro precisamos importar as dependências da AWS:

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-lambda-java-core</artifactId>
    <version>1.2.1</version>
</dependency>
<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-lambda-java-events</artifactId>
    <version>3.6.0</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

Como este aplicativo irá interagir com a Blockchain Algorand, você também precisa importar o Algorand Java SDK.

<dependency>
    <groupId>com.algorand</groupId>
    <artifactId>algosdk</artifactId>
    <version>1.8.0</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

Finalmente, para empacotar corretamente o software, você precisa configurar o plug-in Shade para Maven em <plugins>.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.2.4</version>
    <configuration>
    </configuration>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Enter fullscreen mode Exit fullscreen mode

O pom.xml deve adicionar o semelhante assim: pom.xml

Observação: as versões de cada dependência podem ser alteradas no momento em que você tenta implantar em seu serviço.

Antes de continuar, certifique-se de que seu projeto seja compilado usando o mvn package.

2. A estrutura do projeto

As funções do Lambda são orientadas por eventos. O manipulador é o método que processa eventos. Quando nosso serviço serverless é invocado, o Lambda executa o método do manipulador. Quando termina seu trabalho, fica disponível para tratar de outro evento.

Neste tutorial, construiremos dois manipuladores diferentes:

GetAmountHandler(...)
SendAlgoHandler(...)

O primeiro recupera a quantidade total de Algo mantido por uma conta Algorand.
A segunda, um pouco mais complexa, mostra como enviar Algos de uma conta para outra.
Após implantar o aplicativo na AWS, você poderá escolher qual função invocar.
Para interagir com a blockchain Algorand, usaremos um serviço Class chamado Algoservice . Essa Class contém alguns métodos que encapsulam operações mais complexas na blockchain.

initAccount()
getAccountAmount(String address)
sendAlgo(String receiverAddress, long amount)
waitForConfirmation(String txId, int timeout)

Examinaremos cada um desses métodos detalhadamente mais adiante no artigo.

Neste projeto, usaremos duas classes adicionais que representam os “modelos” para a solicitação e a resposta. Eles são úteis para gerenciar os objetos JSON que passam e retornam parâmetros para nossa função. As duas classes são:

RequestModel
ResponseModel

3. GetAmountHandler

Como mencionado, um manipulador é um ponto de entrada para nossa função. Ele é invocado quando a função Lambda é chamada. Vamos dar uma olhada no trecho de código:

public class GetAmountHandler implements RequestHandler<String, Long> {
    AlgoService algoService = new AlgoService(
                System.getenv("CORE_API_ADDR"),
                Integer.parseInt(System.getenv("CORE_API_PORT")),
                System.getenv("CORE_API_TOKEN"),
                System.getenv("INDEXER_API_ADDR"),
                Integer.parseInt(System.getenv("INDEXER_API_PORT")));

    @Override
    public Long handleRequest(final String address, final Context context) {

        LambdaLogger logger = context.getLogger();
        Long amount = algoService.getAccountAmount(address).orElse(-1L);

        logger.log("Amount: " + amount);
        return amount;
    }
}
Enter fullscreen mode Exit fullscreen mode

Nota: Você terá que atualizar as variáveis ​​de ambiente com informações válidas para seu projeto.

Como você pode ver, o código é muito simples.

A biblioteca java aws-lambda-java-core define duas interfaces para métodos de manipulador:

RequestHandler
RequestStreamHandler

O primeiro aceita Objects como parâmetros e o segundo aceita Streams.
Usaremos o primeiro em nossos exemplos - RequestHandler.

É um tipo genérico que aceita dois parâmetros: o tipo de input e o tipo de output (ambos devem ser objetos). O Java Runtime desserializa o evento em um objeto do tipo especificado para o input e serializa o output em um objeto do tipo de output.

No nosso caso, a Class GetAmountHandler implementa a interface RequestHandler . Os dois tipos são tipos de Request e Response, respectivamente: ele aceita um String como input e retornará um Long.

A interface RequestHandler exige que você implemente o método HandleRequest, que acidentalmente aceita um String e retorna um Long.

O parâmetro extra Context contém informações úteis sobre a instância atual da função.

Quando nosso Lambda é invocado, ele receberá o endereço Algorand e será verificado (a String). Ao final do cálculo, o próprio Lambda enviará de volta a quantidade total de Algo pertencente ao endereço (a Long).

Como não temos controle sobre a execução do Lambda, a produção de logs é importante.

Para isso, podemos usar o objeto LambdaLogger fornecido pelo objeto Context da seguinte forma:

LambdaLogger logger = context.getLogger();
Enter fullscreen mode Exit fullscreen mode

O código do manipulador é muito simples. Instanciamos um objeto AlgoService e chamamos seu método getAlgoAmount().

Este método recupera a quantidade de Algos de propriedade do endereço que passamos como input. AlgoService será analisado mais detalhadamente abaixo.

Para inicializar o objeto AlgoService, usamos informações contidas nas variáveis ​​de ambiente. Na função Lambda, podemos recuperar as variáveis ​​de ambiente usando a chamada System.getEnv(). Dessa forma, podemos manter informações confidenciais fora do código e obter mais reutilização.
O método getAlgoAmount() retorna um Optional, portanto, para obter a resposta, precisamos verificar se o opcional está vazio (neste caso, retornaremos -1L, que representa um erro) ou se contém um valor que será retornado.

4. SendAlgoHandler

Para entender melhor a potencialidade serverless, vamos analisar um segundo exemplo um pouco mais complexo.

Vamos definir um segundo Handler chamado SendAlgoHandler:

public class SendAlgoHandler implements RequestHandler<RequestModel, ResponseModel> {
    AlgoService algoService;

    public SendAlgoHandler(AlgoService algoService) {
        this.algoService = new AlgoService(
                System.getenv("CORE_API_ADDR"),
                Integer.parseInt(System.getenv("CORE_API_PORT")),
                System.getenv("CORE_API_TOKEN"),
                System.getenv("INDEXER_API_ADDR"),
                Integer.parseInt(System.getenv("INDEXER_API_PORT")),
                System.getenv("ACC_PASSPHRASE"));
    }
      [...]
}
Enter fullscreen mode Exit fullscreen mode

Desta vez, implementamos a interface RequestHandler<RequestModel, ResponseModel>.
RequestModel e ResponseModel são os tipos de solicitação e resposta, respectivamente. São dois POJO (Plain Old Java Classes) muito simples:

public class RequestModel {
    String address;
    Long amount;

      [...] //Getters and Setters
}

Enter fullscreen mode Exit fullscreen mode

e

public class ResponseModel {
    private String txId;
    private String msg;

      [...] //Getters and Setters
}
Enter fullscreen mode Exit fullscreen mode

Conforme mencionado, o Java Runtime desserializa automaticamente o evento no objeto RequestModel e serializa a resposta no objeto ResponseModel. Veremos isso com mais detalhes na última parte deste tutorial.

Além disso, observe que invocamos um construtor diferente com mais um parâmetro: a senha da conta (ACC_PASSPHRASE). Isso porque queremos enviar alguns Algos da nossa carteira para outro endereço e temos que assinar a transação (o que só é possível se tivermos acesso total à nossa conta).

Vamos analisar o código do método HandleRequest da classe SendAlgoHandler:

public ResponseModel handleRequest(final RequestModel request, final Context context) {
    LambdaLogger logger = context.getLogger();
    try {
        String txId = algoService.sendAlgo(request.getAddress(), request.getAmount());

        logger.log("Transaction executed");
        return new ResponseModel(txId,"Transaction executed");
    }
    catch (Exception e) {
        logger.log("Transaction Failed");
        return new ResponseModel("", "Transaction Failed");
    }
}
Enter fullscreen mode Exit fullscreen mode

Novamente, o código é muito simples, porque a lógica Algorand está oculta em AlgoService.
Simplesmente chamamos seu método sendAlgo() passando o endereço de destino e a quantidade de microAlgos a serem enviados.
Este método retorna o id da transação Algorand que contém nossa transferência. Podemos então criar um objeto ResponseModel, usando este id de transação e uma mensagem e usá-lo na instrução de retorno.

Se ocorrer um erro, um objeto ResponseModel com um TxId vazio e uma mensagem de falha será retornado.

5. A classe AlgoService

A classe AlgoService permite que você interaja com a blockchain Algorand. Para o código completo, consulte o repositório do Github: algo-serverless/AlgoService

Neste tutorial, revisaremos apenas a parte mais importante da aula.
Primeiro de tudo, ela tem dois construtores diferentes. O segundo tem um parâmetro extra, a senha da conta, e deve ser usado se você precisar assinar uma transação (como o SendAlgoHandler exemplo em #4).

A classe tem três métodos:

getAccountAmount
sendAlgo
waitForConfirmation

GETALGOAMOUNT

A parte mais importante é a seguinte:

Address destAddress = new Address(address);
accountResponse = algodClient.AccountInformation(destAddress).execute();
Enter fullscreen mode Exit fullscreen mode

Esse método recebe uma string de endereço como input e chama a função do Algorand Java SDK AccountInformation para recuperar a quantidade total de Algo armazenado na carteira.

SENDALGO

Esta função recebe o endereço de destino e a quantidade de microAlgo a transferir.
A parte importante do código é:

com.algorand.algosdk.transaction.Transaction tx =
com.algorand.algosdk.transaction.Transaction.PaymentTransactionBuilder()
                .sender(algoAddress).note(note.getBytes()).amount(amount)
                .receiver(address).suggestedParams(params).build();

SignedTransaction signedTx = algoAccount.signTransaction(tx);
byte[] encodedSignedTx = Encoder.encodeToMsgPack(signedTx);

Response<PostTransactionsResponse> txResponse = algodClient.RawTransaction().rawtxn(encodedSignedTx).execute();
Enter fullscreen mode Exit fullscreen mode

Como você pode ver, preparamos a transação, depois assinamos com nossa chave privada (com a chamada signTransaction) e, finalmente, a enviamos para a blockchain (a parte RawTransaction ).

WAITFORCONFIRMATION

Após enviar uma transação, devemos aguardar até que ela seja aceita e efetivamente registrada na blockchain. A transação waitForConfirmation atende a esse propósito.

Não vamos descrevê-la, pois é uma funcionalidade bem conhecida (você pode encontrá-la na documentação oficial).

6. Implantação na AWS

Primeiro de tudo, temos que empacotar nossa função de maneira adequada. Podemos fazer isso usando o seguinte comando Maven:

mvn clean package
Enter fullscreen mode Exit fullscreen mode

Este comando produz um pacote jar na pasta “target” com o nome “algoserverless-1.0.jar”. Graças ao plugin shade no pom.xml, este estará no formato correto para ser implantado na AWS.

Observação: há muitas maneiras diferentes de implantardeploy um aplicativo Java como uma função do Lambda. Usaremos um dos mais simples: implantação manual. Considere, no entanto, que esta pode não ser a melhor escolha em muitos casos… mas é boa o suficiente para este tutorial.

Agora você está pronto para criar uma função do Lambda. Faça login no console da AWS e selecione o serviço Lambda.
Selecione “Author from Scratch” e em “Basic information” escreva um nome e selecione “Java 11 (Corretto)” para o tempo de execução. Deixe a escolha padrão para as outras opções.

Image description

Clique em “Criar” na parte inferior da página. Depois de um tempo, seu novo Lambda estará pronto, como mostra a imagem abaixo.

Image description

Temos que carregar nosso código-fonte, agora. Selecione "Upload from” e depois “.zip ou .jar” na seção de código-fonte. Esta não é a melhor opção, pois nosso “jar” é maior que 10MB. Devemos usar o armazenamento S3, mas estamos tentando manter este tutorial o mais simples possível.

Você pode selecionar nosso pacote .jar (algoserverless-1.0.jar) e salvá-lo. Após alguns segundos, estaremos prontos para testar nosso Lambda.

Agora temos que definir qual manipulador deve ser invocado. Na guia "Code", role para baixo até o painel "Runtime settings" e clique no botão editar. Escreva o seguinte texto na caixa de texto Handler (como você pode ver, é formado pelo nome do pacote e da classe):

algoserverless.GetAmountHandler::handleRequest
Enter fullscreen mode Exit fullscreen mode

Antes de prosseguir, precisamos fazer um último passo. Você se lembra dos métodos Handler? Eles obtiveram alguns parâmetros de variáveis ​​de ambiente.

Para passar essas variáveis ​​para o nosso Lambda, podemos selecionar a aba “Configuration” e depois “Environment variables” à esquerda.

As variáveis ​​a definir são:

- ACC_ADDR: <Your account Address>
- ACC_PASSPHRASE: <25 words passphrase of your account>
- CORE_API_ADDR: https://testnet.algoexplorerapi.io/
- CORE_API_PORT: 443
- CORE_API_TOKEN: null
- INDEXER_API_ADDR: https://testnet.algoexplorerapi.io/idx2
- INDEXER_API_PORT: 443
Enter fullscreen mode Exit fullscreen mode

Image description

NOTA : você deve escrever as 25 palavras da senha uma após a outra, separadas por um espaço - ou seja:

ACC_PASSPHRASE: tourist wish evoke [...] surprise abstract

A senha é armazenada apenas no servidor como uma variável de ambiente e nunca sai dele. Ela só pode ser acessada ou modificada pelo administrador da conta lambda.

Para usar outros serviços (ou até mesmo seu próprio nó) você só precisa alterar os parâmetros adequadamente (por exemplo: “CORE_API_ADDR: https://node.algoexplorerapi.io/" ). Você provavelmente precisará definir o token da API… e é claro, um endereço de conta válido e uma senha.

7. Teste as funções

Agora estamos prontos para testar o Lambda. Vá para a guia de teste e selecione “new event” e depois o modelo “hello-world”.
Na área de texto, você deve definir o input passada para o nosso Handler. Para isso GetAmountHandler, precisamos de uma string (o endereço da carteira que você deseja obter as informações. Não se esqueça das aspas duplas).

Image description

Por fim, clique no botão Testar.

Após alguns momentos (é mais lento na primeira vez que você chama a função) você receberá a seguinte mensagem: “Execution result: succeeded”. Se você clicar em “details” poderá ver o resultado retornado pela função (um número que representa a quantidade de microAlgos retidos na carteira).

Para testar a função SendAlgo, precisamos fazer apenas algumas alterações.

Na guia "Code", role para baixo até a seção "Runtime settings" e clique em Editar.
Substitua o manipulador pelo seguinte e clique em “Salvar”.

algoserverless.SendAlgoHandler::handleRequest
Enter fullscreen mode Exit fullscreen mode

Também precisamos alterar oa input na guia "Test". Temos que fornecer um objeto JSON (que será desserializado automaticamente no objeto java RequestModel).
Este é um exemplo de input:

{
    "address": "HYX5...MKGE",
    "amount": 100000
}
Enter fullscreen mode Exit fullscreen mode

Você pode clicar novamente no botão "Testar". Desta vez o SendAlgoHandler será invocado.

Novamente, depois de um tempo, recebemos a mensagem “Execution result: succeeded” e nos detalhes, podemos ver o objeto JSON que recebemos em resposta.

{
  "txId": "GNMS...RFEQ",
  "msg": "Transaction executed"
}
Enter fullscreen mode Exit fullscreen mode

E voilà! Aprendemos como implementar um aplicativo serverless.
Este projeto é apenas um template, mas você pode usá-lo para desenvolver uma aplicação mais complexa na Blockchain Algorand. Divirta-se com isso!

Este artigo foi publicado por Portal do desenvolvedor algorand e traduzido por Arnaldo Campos. Você pode ver o artigo original aqui.

Top comments (0)