WEB3DEV

Cover image for Pagamentos ASA Para um Serviço de Contrato Inteligente Usando Algorand
Panegali
Panegali

Posted on • Atualizado em

Pagamentos ASA Para um Serviço de Contrato Inteligente Usando Algorand

Visão geral

Este artigo apresenta uma solução de como usar o pagamento ASA para um serviço de contrato inteligente usando Algorand. Vamos implementar isto usando o Algo Builder.

O que é necessário

Bom conhecimento sobre Blockchain e Algorand.
Introdução detalhada ao algob.
Conhecimento detalhado sobre ativos, contas, transações.
Conhecimento detalhado sobre assinaturas inteligentes, contratos inteligentes algorand e contratos inteligentes.

Estrutura do projeto

contracts:(algob-project)
├── assets
   ├── asa.yaml
   ├── clear.py
   ├── escrow.py
   ├── stateful.py
├── scripts
   ├── deploy.js
├── package.json
Enter fullscreen mode Exit fullscreen mode

dapp contém app react.


Sumário

1 . Visão geral 2

2 . Contratos

3 . Conta de garantia (contrato sem estado)

4 . Contrato de estado

5 . DApp Web


Visão geral 2

Nesta solução temos um contrato inteligente (um app) que oferece um serviço e só registramos um novo usuário se ele pagar uma certa quantidade específica de tokens ASA.

Você pode encontrar o código para a solução aqui.

Nota: Um usuário só pode se registrar uma vez e pagar o dapp warcraft várias vezes.

A solução consiste em duas partes:

  • contracts: Esta pasta consiste na implementação de ASA, assinaturas inteligentes e contratos inteligentes.
  • dapp: Esta pasta consiste na interface de usuário para interagir com contratos implantados e ASA.

Contratos

A pasta contracts contém a lógica para esta solução. Nesta pasta vamos realizar as seguintes operações:

  • Criar um token: WarcraftCoin (token ASA)
  • Criar um aplicativo: Warcraft - tem apenas uma função: registrar (user_addr)

Estamos usando modelos PyTEAL, você pode ler mais sobre isso aqui.

Conta de garantia

A conta de garantia será usada para depositar o token ASA (token warcraft).

Neste contrato temos as ramificações optin e register.

Somente o manager pode optar por enviar ASA para o endereço de garantia, isso é feito para que um usuário mal-intencionado não possa enviar spam de ASA para o endereço de garantia.

# transação de opção de participação
# Nota: estamos verificando que a primeira transação é o pagamento com o valor 0
# e enviado pelo manager da loja, porque não queremos outro
# usuário participando com muitos asa/app e bloqueando este endereço
opt_in = And(
    Gtxn[0].amount() == Int(0),
    Gtxn[0].sender() == Tmpl.Addr("TMPL_MANAGER"),
    Gtxn[1].type_enum() == TxnType.AssetTransfer,
    Gtxn[1].asset_amount() == Int(0)
)
Enter fullscreen mode Exit fullscreen mode

O ramo de registro garante que o contrato de estado seja chamado.

register = And(
    commons_checks,
    Gtxn[1].type_enum() == TxnType.ApplicationCall,
    Gtxn[1].application_id() == Tmpl.Int("TMPL_APPLICATION_ID"),
    Gtxn[1].sender() == Gtxn[0].asset_sender()
)
Enter fullscreen mode Exit fullscreen mode

Contrato de estado

No estado deste contrato é mencionado o endereço da conta de garantia da loja e o total registrado.

Além disso, codificamos rigidamente TMPL_MANAGER (gerenciador de aplicativo) usando a variável de modelo (definida durante o carregamento do contrato inteligente).

Este contrato tem duas ramificações: on_update_escrow, on_register.

A ramificação on_update_escrow só pode ser chamada pelo gerenciador de aplicativos para atualizar o endereço lsig de garantia.

Nota: primeiro precisamos criar o aplicativo sem definir o endereço da conta de garantia, porque o ID do aplicativo é necessário para inicializar corretamente o lsig de garantia.

on_update_escrow = Seq([
    Assert(
        And(
            basic_checks,
            Txn.sender() == Tmpl.Addr("TMPL_MANAGER")
        )
    ),
    App.globalPut(escrow, Txn.application_args[1]),
    Return(Int(1))
])
Enter fullscreen mode Exit fullscreen mode

A ramificação on_register é usada para registrar um novo usuário no contrato em troca de tokens ASA (WarcraftCoin). Nesta ramificação verificamos que o usuário pagou exatamente 1 WarcraftCoin para o depósito. Finalmente, em seu estado local, definimos warcraft = 1(para dar a ele acesso ao jogo) e incrementamos o contador global registrado em 1.

on_register = Seq([
        Assert(
            And(
                basic_checks,
                Gtxn[0].type_enum() == TxnType.AssetTransfer,
                Gtxn[0].asset_amount() == Int(1),
                Gtxn[0].xfer_asset() == Tmpl.Int("TMPL_WARCRAFT_TOKEN"),
                Gtxn[0].asset_receiver() == App.globalGet(escrow)
            )
        ),
        App.localPut(Int(0), Bytes("warcraft"), Int(1)),
        App.globalPut(total_registered, Add(App.globalGet(total_registered), Int(1))),
        Return(Int(1))
])
Enter fullscreen mode Exit fullscreen mode

1

2

3

Preparamos uma amostra de scripts de implantação (para ASA e Application) em scripts/deploy.js.

DApp Web

Criamos um dapp web para demonstrar e interagir com os contratos implantados. Ele usa @algo-builder/web e Algosigner.

Ele é criado usando create-react-app.

Você pode encontrar o código completo em nosso repositório de modelos dapp.

O usuário pode usar este dapp para pagar a moeda do warcraft e se registrar no aplicativo. Este dapp possui um widget de pagamento que lida com essa transação de grupo.

Primeiro você precisa definir o ID ASA (WarcraftCoin) e o ID App no código widget. Você pode encontrar esses valores após implantar os contratos (nos artefatos do Algo Builder).

Depois de definir os valores, você pode iniciar o aplicativo usando yarn run start.

Para executar a transação, criamos um novo contexto AlgoSigner e usamos @algo-builer/web para criar uma transação.

const web = new WebMode(AlgoSigner, CHAIN_NAME);
const groupTx = [
    {
        type: types.TransactionType.TransferAsset,
        sign: types.SignType.SecretKey,
        fromAccountAddr: fromAddress,
        toAccountAddr: toAddress,
        assetID: assetIndex,
        amount: 1,
        payFlags: {},
    },
    {
        type: types.TransactionType.OptInToApp,
        sign: types.SignType.SecretKey,
        fromAccountAddr: fromAddress,
        toAccountAddr: toAddress,
        appID: appIndex,
        payFlags: {},
    }
];
// mostrar o estado de carregamento no botão enquanto enviamos & esperamos pela resposta da transação
setLoading (true);
let response = await web.executeTransaction(groupTx);
console.log(response);
Enter fullscreen mode Exit fullscreen mode

4

5

6


Este artigo foi escrito por Amit Yadav e publicado no Portal do desenvolvedor Algorand. Traduzido por Marcelo Panegali.

Top comments (0)