WEB3DEV

Cover image for Olá Beaker - Algorand
Dimitris Carvalho Calixto
Dimitris Carvalho Calixto

Posted on

Olá Beaker - Algorand

Esse artigo foi escrito por: Ben Guidarelli e traduzido por Dimitris Calixto, artigo original disponível aqui

Olá Desenvolvedor

Se você já escreveu e implantou um Contrato Inteligente para Algorand usando PyTeal antes de hoje, você provavelmente mastigou muito vidro para fazer isso, muito bem feito!

Tenha coragem; a equipe Algorand tem trabalhado duro para melhorar a experiência de desenvolvimento.

Antes de mergulharmos nas melhorias, vamos rever algumas coisas comuns com as quais as pessoas lutam enquanto desenvolvem.

Organização do Código

Quando você começa a escrever um contrato, como você estrutura a lógica do programa? Como você lida com as entradas e saídas do contrato?

Um padrão muito comum para escrever o programa de aprovação em PyTeal é algo parecido com:


def approval():

        #...

        return Cond(

            # Inferir que isto é criado

            [Txn.application_id() == Int(0), do_create_method()],

            # Verificação manual completa

            [Txn.on_complete() == OnComplete.UpdateApplication, do_update()],

            # Use alguma const  que você tem que comunicar de alguma forma ao _caller_

            # para encaminhar para o método certo, depois descobre como analisar o resto 

            # dos argumentos do app

            [Txn.application_args[0] == "do_the_thing", do_the_thing()],

            #...

        )

    # ...

    approval_teal = compileTeal(approval(), mode=Mode.Application, version=6)

Enter fullscreen mode Exit fullscreen mode

Isto funciona, mas é difícil de entender para um recém-chegado.

Interagindo com a Aplicação

Para implantar um aplicativo on-chain, você submete uma transação de criação de aplicativo. Nesta transação, você especifica os programas TEAL compilados, o esquema de aplicação ("Quantos uints globais eu preciso novamente?"), e páginas extras do programa.

A chamada de um aplicativo on-chain envolve a criação de transações de chamada de aplicativo com o roteamento apropriado e argumentos de dados se não usar a ABI.

Mesmo quando se usa a ABI, os métodos de chamada envolvem a importação da descrição do contrato JSON e a construção de uma AtomicTransactionComposer, passando argumentos como uma lista sem contexto sobre o que eles devem ser.

Gerenciando o estado

O gerenciamento do esquema de estado da aplicação é muitas vezes feito manualmente com constantes para as chaves e lembrando-se de qual deve ser o tipo associado.

A criação da aplicação exige que você saiba o número e o tipo de cada valor de estado que não tem uma maneira fácil de obter automaticamente.

Depurando

A depuração pode ser um pesadelo ao tentar descobrir uma mensagem de erro como assert failed: pc=XXX

Image

Testando

Os contratos de teste podem ser difíceis e pouca orientação é fornecida. Muitas vezes é necessário reconstruir grande parte da infra-estrutura do frontend para testar diferentes entradas/saídas.

Os devs fizeram algo

Agora, vamos ver como as coisas mudaram.

ABI

A ABI fornece padrões para tipos de codificação, descrevendo métodos e chamadas de métodos de roteamento interno para a lógica apropriada.

Com a ABI, temos agora uma maneira padrão de organizar o código e interagir com a aplicação.

Mais detalhes sobre a ABI estão disponíveis aqui

Compositor de Transações Atômicas

Usando o compositor de transações atômicas e as especificações da ABI para seu contrato, você pode facilmente compor transações de grupo atômico e ter os argumentos codificados e os valores de retorno decodificados para você!

Pyteal ABI

PyTeal agora trata da codificação/decodificação de tipos de dados em um contrato. A classe PyTeal Router oferece até mesmo uma maneira de lidar com a lógica de roteamento de métodos, passando os tipos decodificados diretamente para um método, e fornece as especificações do contrato ABI.

Por exemplo, se você quiser um método que acrescenta 1 a um uint8, você pode escrevê-lo assim:


@router.method

def increment_my_number(input: abi.Uint8, *, output: abi.Uint8):

    return output.set(input.get() + Int(1))

Enter fullscreen mode Exit fullscreen mode

Image

Muito. Mais agradável.

Para mais informações, veja o post do blog aqui

Para documentação detalhada sobre a PyTeal ABI veja a documentação aqui

Mapas de origem

O mapeamento de um pc retornado de uma mensagem de erro ficou muito mais fácil. Agora você pode compilar TEAL com a flag sourcemap ativada. O mapa resultante volta de acordo com esta especificação e pode ser decodificado com qualquer um dos SDKs usando o novo objeto SourceMap.

Isto significa que você pode associar um pc diretamente à linha TEAL de origem, com todos os nomes familiares e formatação que você está acostumado a ver.

Olá Beaker

Hoje estamos compartilhando o Beaker, um framework de desenvolvimento de contratos inteligentes destinado a melhorar ainda mais a experiência de desenvolvimento.

O Beaker aproveita as melhorias citadas acima, nos permitindo fornecer muito mais estruturas às aplicações.

No entanto, ainda é experimental.

Image

Toda a documentação está aqui.

Vamos ver como Beaker resolve nossos problemas.

Organização do código

Beaker fornece uma maneira padrão de organizar o código usando uma classe para encapsular a funcionalidade.


from beaker import Application, external

class MyApp(Application):

    @external

    def add(self, a: abi.Uint64, b: abi.Uint64, *, output: abi.Uint64):

        return output.set(a.get() + b.get())

Enter fullscreen mode Exit fullscreen mode

Esta é uma aplicação completa! Tem um programa de aprovação, um limpar programa, um estado implicitamente vazio. Os métodos definidos são fornecidos em um contrato da ABI para exportar para outros clientes.

O @external decorator do método expõe nosso método definido aos chamadores e fornece roteamento com base em sua assinatura do método. A assinatura do método resultante deste método é add(uint64,uint64)uint64.

O método add é um método PyTeal ABI (em sua maioria) válido. A exceção que o torna mais válido aqui, é que o Beaker permite que você passe self, permitindo referências a variáveis de instância.

Há muito mais que você pode fazer, incluindo; controle de acesso, mudando quais tipos OnComplete podem ser usados para chamá-lo, ou marcando-o como um método read-only.

Para mais informações, consulte a documentação do Decorator

Interagindo com a aplicação

Beaker fornece um ApplicationClient para lidar com necessidades comuns como a criação/opção de métodos de chamada.

Ele usa sua definição de Application para fornecer o contexto como o esquema ou os argumentos necessários para os métodos que estão sendo chamados.


from beaker import sandbox, client

# obtém o primeiro acct no sandbox

acct = sandbox.get_accts().pop()

# cria um cliente de aplicação

app_client = client.ApplicationClient(

    client=sandbox.get_algod_client(), 

    app=MyApp(), 

    signer=acct.signer

)

# implanta o aplicativo on-chain

app_client.create()

# chama o método 

result = app_client.call(MyApp.add, a=32, b=10)

print(result.return_value) # 42

# agora vá lá fora e toque em um pouco de grama porque você está pronto

Enter fullscreen mode Exit fullscreen mode

Para mais informações, veja a documentação do ApplicationClient

Gerenciando Estado

O Beaker permite declarar valores de estado tipados como variáveis de classe


from beaker import Application, ApplicationStateValue, external

class CounterApp(Application):

    counter = ApplicationStateValue(TealType.uint64)

    @external

    def incr_counter(self, incr_amt: abi.Uint64):

        self.counter.set(self.counter + incr_amt.get())

Enter fullscreen mode Exit fullscreen mode

Podemos até inspecionar nossa aplicação para ver quais são os requisitos de seu esquema!


app = CounterApp() 

print(app.app_state.schema())

Enter fullscreen mode Exit fullscreen mode

Para mais informações, veja a documentação de Estado

Depurando

Beaker melhora a mensagem de erro pc=xxx usando o ponto final do mapa de origem durante a compilação e mapeando o pc de volta para o teal de origem. O LogicException resultante permite que você veja o número exato da linha Teal da fonte com todos os nomes úteis de sub-rotinas e quaisquer comentários no teal da fonte.

Abaixo está o resultado de uma simples impressão de uma LogicException me dizendo exatamente onde meu programa falhou. Mais importante ainda, ele fornece o contexto da fonte TEAL mostrando-me por que ele falhou.


Txn WWVF5P2BXRNQDFFSGAGMCXJNDMZ224RJUGSMVPJVTBCVHEZMOMNA had error 'assert failed pc=883' at PC 883 and Source Line 579: 

        store 50

        store 49

        store 48

        store 47

        // correct asset a

        load 50

        txnas Assets

        bytec_0 // "a"

        app_global_get

        ==

        assert          <-- Error

        // correct asset b

        load 51

        txnas Assets

        bytec_1 // "b"

        app_global_get

        ==

        assert

        // correct pool token

        load 49

Enter fullscreen mode Exit fullscreen mode

Também estamos trabalhando para fazer com que este mapeamento volte à fonte PyTeal com este problema

Testando

Inicialmente o Beaker fornece auxiliares para:

Recuperar e comparar saldos de contas. Útil para garantir que as quantidades corretas de algos ou Tokens foram transferidas de ou para as contas relevantes.

Funcionalidade de teste de unidade passando por entradas e comparando com as saídas esperadas. Útil para testar comportamentos pequenos e autocontidos.

Para mais informações, consulte a documentação de teste.

Mais

Há muito mais que não foi abordado aqui e ainda há muito a ser feito. O Beaker precisa de sua ajuda para melhorar!

Veja a documentação https://beaker.algo.xyz

O código aqui https://github.com/algorand-devrel/beaker. Por favor, sinta-se à vontade para abrir uma issue ou PRs!

E para qualquer pergunta, marque @barnji no canal #beaker no discord do Algorand

Top comments (0)