Micro Agents: Enviando Tokens
1
0
Fetch.ai | Jul 18, 2023

Bem-vindo! Neste tutorial, mostraremos como configurar dois agentes, alice e bob, utilizando o framework Microgents, com alice enviando periodicamente solicitações de pagamento para bob e bob processando essas solicitações enviando pagamentos e fornecendo informações de transação de volta para alice.
Em primeiro lugar, precisamos de criar um script .py para este exemplo. Vamos nomeá-lo como send_tokens.py.
touch sending_tokens.py
Vamos precisar de importar os módulos necessários do framework uAgents:
from uagents import Agent, Bureau, Context, Model
from uagents.network import wait_for_tx_to_complete
from uagents.setup import fund_agent_if_low
- Agent: Usado para criar agentes autónomos.
- Bureau: Gerir os agentes e a sua execução.
- Context: fornece informações de contexto aos agentes durante a execução.
- Model: Utilizado para definir modelos de dados para troca de mensagens entre agentes.
- wait_for_tx_to_complete: Aguarda a conclusão de uma transação.
- fund_agent_if_low: Garante que um agente tenha fundos suficientes na sua carteira.
Depois necessitamos de definir dois modelos de dados: PaymentRequest e TransactionInfo.
class PaymentRequest(Model):
wallet_address: str
amount: int
denom: str
class TransactionInfo(Model):
tx_hash: str
AMOUNT = 100
DENOM = "atestfet"
O modelo PaymentRequest() representa uma solicitação de pagamento que contém os seguintes atributos:
- wallet_address: é uma string, str, representando o endereço da carteira para a qual o pagamento deve ser enviado.
- amount: é um número inteiro, int e representa o valor do pagamento.
- denom: uma string, str, que é a designação do pagamento.
O modelo TransactionInfo() representa informações sobre uma transação e contém um único atributo, tx_hash do tipo string, str.
Adicionalmente, precisamos de configurar os valores para as variáveis AMOUNT e DENOM, que definem o valor padrão e designação para as solicitações de pagamento.
Agora podemos prosseguir definindo os nossos agentes, alice e bob:
alice = Agent(name="alice", seed="alice secret phrase")
bob = Agent(name="bob", seed="bob secret phrase")
fund_agent_if_low(alice.wallet.address())
fund_agent_if_low(bob.wallet.address())
Após inicializar os agentes, a função fund_agent_if_low() é chamada tanto para alice quanto para bob de modo a garantir que eles tenham fundos suficientes nas suas carteiras para realizar as transações pretendidas.
Agora podemos definir as funções e comportamentos dos nossos agentes:
@alice.on_interval(period=10.0)
async def request_funds(ctx: Context):
await ctx.send(
bob.address,
PaymentRequest(
wallet_address=str(ctx.wallet.address()), amount=AMOUNT, denom=DENOM
),
)
Isto define um manipulador de eventos para alice utilizando o decorador @alice.on_interval(). Este manipulador de eventos é acionado em intervalos regulares especificados pelo parâmetro period, que é definido como 10,0 segundos neste caso.
A função do manipulador de eventos é denominada request_funds() e recebe um parâmetro ctx do tipo Context. Dentro da função, alice envia uma mensagem de solicitação de pagamento para bob utilizando o método ctx.send().
O método ctx.send é chamado com os seguintes argumentos:
- O endereço do destinatário, bob.address, especifica que a mensagem deve ser enviada para bob. A mensagem é uma instância do modelo PaymentRequest(). Contém o endereço da carteira de alice (str(ctx.wallet.address())), o valor (AMOUNT) e a denominação (DENOM).
@alice.on_message(model=TransactionInfo)
async def confirm_transaction(ctx: Context, sender: str, msg: TransactionInfo):
ctx.logger.info(f"Received transaction info from {sender}: {msg}")
tx_resp = await wait_for_tx_to_complete(msg.tx_hash)
coin_received = tx_resp.events["coin_received"]
if (
coin_received["receiver"] == str(ctx.wallet.address())
and coin_received["amount"] == f"{AMOUNT}{DENOM}"
):
ctx.logger.info(f"Transaction was successful: {coin_received}")
Isto define um manipulador de eventos para alice usando o decorador @alice.on_message(). Este manipulador de eventos é acionado quando alice recebe uma mensagem do tipo TransactionInfo de bob.
A função do manipulador de eventos é chamada confirm_transaction() e recebe três parâmetros:
- ctx: uma instância da classe Context, que fornece informações contextuais durante a execução do manipulador de eventos.
- sender: uma string que representa o remetente da mensagem.
- msg: uma instância do modelo TransactionInfo, que contém o hash da transação.
Dentro da função, alice regista uma mensagem informativa utilizando o método ctx.logger.info(), indicando se recebeu as informações da transação do agente remetente, bob, e exibindo o objeto msg.
De seguida, utilizamos a função wait_for_tx_to_complete() para aguardar a finalização da transação especificada pelo tx_hash recebido na mensagem.
Depois da transação estar concluída, o código acede ao evento coin_received da resposta da transação utilizando tx_resp.events[“coin_received”]. Ele verifica se o endereço do destinatário corresponde ao endereço da carteira de alice (str(ctx.wallet.address())) e se o valor recebido corresponde ao valor esperado (AMOUNT + DENOM).
Se as condições forem atendidas, alice regista outra mensagem informativa indicando o sucesso da transação e exibindo os detalhes das moedas recebidas.
@bob.on_message(model=PaymentRequest, replies=TransactionInfo)
async def send_payment(ctx: Context, sender: str, msg: PaymentRequest):
ctx.logger.info(f"Received payment request from {sender}: {msg}")
transaction = ctx.ledger.send_tokens(
msg.wallet_address, msg.amount, msg.denom, ctx.wallet
)
await ctx.send(alice.address, TransactionInfo(tx_hash=transaction.tx_hash))
Definimos agora um manipulador de eventos para bob utilizando o decorador @bob.on_message(). Este manipulador de eventos é acionado sempre que bob recebe uma mensagem do tipo PaymentRequest de alice.
A função do manipulador de eventos é denominada send_payment() e recebe três parâmetros:
- ctx: uma instância da classe Context, que fornece informações contextuais durante a execução do manipulador de eventos.
- sender: uma string que representa o remetente da mensagem.
- msg: uma instância do modelo PaymentRequest, que contém os detalhes da solicitação de pagamento.
Na função, bob registra uma mensagem informativa usando o método ctx.logger.info(), indicando o recebimento de uma solicitação de pagamento do agente remetente, bob, e exibindo o objeto msg.
De seguida, o código executa uma transação de pagamento usando o método ctx.ledger.send_tokens(). Ele usa o endereço da carteira (msg.wallet_address), valor (msg.amount), denominação (msg.denom) e ctx.wallet como parâmetros. Este método é responsável pelo envio do pagamento solicitado.
Depois da transação estar concluída, bob envia uma mensagem de volta para alice para informá-la sobre a transação, usando ctx.send(). A mensagem é criada usando o modelo TransactionInfo com o tx_hash obtido da resposta da transação. O método await ctx.send() é utilizado para enviar esta mensagem para alice usando seu endereço (alice.address).
Por fim, os agentes são adicionados a um objeto Bureau para serem executados em conjunto.
bureau = Bureau()
bureau.add(alice)
bureau.add(bob)
if __name__ == "__main__":
bureau.run()
O código geral para este exemplo deve ter a seguinte aparência:
from uagents import Agent, Bureau, Context, Model
from uagents.network import wait_for_tx_to_complete
from uagents.setup import fund_agent_if_low
class PaymentRequest(Model):
wallet_address: str
amount: int
denom: str
class TransactionInfo(Model):
tx_hash: str
AMOUNT = 100
DENOM = "atestfet"
alice = Agent(name="alice", seed="alice secret phrase")
bob = Agent(name="bob", seed="bob secret phrase")
fund_agent_if_low(alice.wallet.address())
fund_agent_if_low(bob.wallet.address())
@alice.on_interval(period=10.0)
async def request_funds(ctx: Context):
await ctx.send(
bob.address,
PaymentRequest(
wallet_address=str(ctx.wallet.address()), amount=AMOUNT, denom=DENOM
),
)
@alice.on_message(model=TransactionInfo)
async def confirm_transaction(ctx: Context, sender: str, msg: TransactionInfo):
ctx.logger.info(f"Received transaction info from {sender}: {msg}")
tx_resp = await wait_for_tx_to_complete(msg.tx_hash)
coin_received = tx_resp.events["coin_received"]
if (
coin_received["receiver"] == str(ctx.wallet.address())
and coin_received["amount"] == f"{AMOUNT}{DENOM}"
):
ctx.logger.info(f"Transaction was successful: {coin_received}")
@bob.on_message(model=PaymentRequest, replies=TransactionInfo)
async def send_payment(ctx: Context, sender: str, msg: PaymentRequest):
ctx.logger.info(f"Received payment request from {sender}: {msg}")
transaction = ctx.ledger.send_tokens(
msg.wallet_address, msg.amount, msg.denom, ctx.wallet
)
await ctx.send(alice.address, TransactionInfo(tx_hash=transaction.tx_hash))
bureau = Bureau()
bureau.add(alice)
bureau.add(bob)
if __name__ == "__main__":
bureau.run()
Estamos prontos para executar o script criado. Certifica-te de guardar o teu script e ativar corretamente o ambiente virtual. No terminal, executa:
python sending_tokens.py
A saída deve ser a seguinte:

Como pode ver, configuramos dois Micro Agentes, Alice e Bob, para participar de um cenário de pagamento. Alice envia solicitações de pagamento para Bob a cada 10 segundos. Bob então processa os pagamentos e envia as informações da transação de volta para Alice para confirmação de que, finalmente, fica registado o status da transação.
Originalmente publicado em https://fetch.ai. em 18 de julho de 2023.
Micro Agents: Enviando Tokens was originally published in Fetch.ai on Medium, where people are continuing the conversation by highlighting and responding to this story.
1
0
Conecte com segurança o portfólio que você está usando para começar.