Skip to content

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

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

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)
)

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()
)

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))
])

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))
])

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);

4

5

6


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