SwiftHTML & CSSSolidityDesenvolvimento de JogosSolana/Rust
22.11.2024

Aula 101: Implementando Leilões na Solana

Nesta aula, vamos explorar como implementar um sistema de leilão simples na blockchain Solana usando Rust. Vamos criar um programa básico de leilão que permite aos usuários criar e participar de leilões.

Configurando seu Ambiente

Antes de mergulharmos no código, certifique-se de ter os seguintes itens instalados:

  • Rust e Cargo
  • Solana CLI
  • Solana Tool Suite

Você pode seguir a documentação oficial do Solana para configurar tudo corretamente.

Definindo o Programa de Leilão

Começaremos definindo a estrutura do nosso leilão. Um leilão consiste em alguns parâmetros principais:

  • ID do Leilão: Identificador único para o leilão.
  • Criador: O endereço da carteira do criador do leilão.
  • Hora de Início: Quando o leilão começa.
  • Hora de Término: Quando o leilão termina.
  • Lance Mínimo: O menor valor que pode ser oferecido.
  • Maior Lance: O maior lance submetido até agora.
  • Maior Licitante: O endereço da carteira do maior licitante.

Definição da Estrutura

Vamos definir a estrutura do nosso leilão em Rust:

use anchor_lang::prelude::*;

#[program]
pub mod leilao {
    use super::*;

    pub fn criar_leilao(ctx: Context<CriarLeilao>, hora_inicio: i64, hora_termino: i64, lance_minimo: u64) -> Result<()> {
        let leilao = &mut ctx.accounts.leilao;
        leilao.criador = *ctx.accounts.criador.key;
        leilao.hora_inicio = hora_inicio;
        leilao.hora_termino = hora_termino;
        leilao.lance_minimo = lance_minimo;
        leilao.maior_lance = 0;
        leilao.maior_licitante = Pubkey::default();
        Ok(())
    }

    pub fn fazer_lance(ctx: Context<FazerLance>, valor: u64) -> Result<()> {
        let leilao = &mut ctx.accounts.leilao;

        // Verifica se o leilão está em andamento
        if Clock::get()?.unix_timestamp < leilao.hora_inicio {
            return Err(ErrorCode::LeilaoNaoIniciado.into());
        }
        if Clock::get()?.unix_timestamp > leilao.hora_termino {
            return Err(ErrorCode::LeilaoEncerrado.into());
        }
        if valor < leilao.lance_minimo || valor <= leilao.maior_lance {
            return Err(ErrorCode::ValorLanceInvalido.into());
        }

        leilao.maior_lance = valor;
        leilao.maior_licitante = *ctx.accounts.licitante.key;

        Ok(())
    }
}

Estrutura da Conta

Agora, precisamos definir a estrutura da conta que irá armazenar os dados do nosso leilão:

#[account]
pub struct Leilao {
    pub criador: Pubkey,
    pub hora_inicio: i64,
    pub hora_termino: i64,
    pub lance_minimo: u64,
    pub maior_lance: u64,
    pub maior_licitante: Pubkey,
}

Tratamento de Erros

Vamos definir alguns códigos de erro para gerenciar possíveis problemas com o leilão:

#[error]
pub enum ErrorCode {
    #[msg("O leilão ainda não começou.")]
    LeilaoNaoIniciado,
    #[msg("O leilão já foi encerrado.")]
    LeilaoEncerrado,
    #[msg("Valor do lance inválido.")]
    ValorLanceInvalido,
}

Interação do Lado do Cliente

Para interagir com o leilão, vamos criar um programa cliente. Primeiro, certifique-se de ter as dependências necessárias em seu Cargo.toml:

[dependencies]
solana-client = "1.9.9"
solana-sdk = "1.9.9"
anyhow = "1.0"

Função Criar Leilão

Veja como você pode criar um leilão a partir do seu cliente:

use solana_sdk::{
    signature::Keypair,
    transaction::Transaction,
};
use solana_client::rpc_client::RpcClient;

fn criar_leilao(cliente: &RpcClient, pagador: &Keypair, dados_leilao: DadosLeilao) -> Result<()> {
    let conta_leilao = Keypair::new();
    let instrução_criar_leilao = leilao::criar_leilao(
        &pagador.pubkey(),
        &conta_leilao.pubkey(),
        dados_leilao.hora_inicio,
        dados_leilao.hora_termino,
        dados_leilao.lance_minimo,
    );

    let transação = Transaction::new_signed_with_payer(
        &[instrução_criar_leilao],
        Some(&pagador.pubkey()),
        &[pagador, &conta_leilao],
        cliente.get_recent_blockhash()?.0,
    );

    cliente.send_and_confirm_transaction(&transação)?;
    Ok(())
}

Função Fazer Lance

Agora, vamos implementar a função para fazer um lance:

fn fazer_lance(cliente: &RpcClient, licitante: &Keypair, id_leilao: Pubkey, valor: u64) -> Result<()> {
    let instrução_fazer_lance = leilao::fazer_lance(&licitante.pubkey(), &id_leilao, valor);

    let transação = Transaction::new_signed_with_payer(
        &[instrução_fazer_lance],
        Some(&licitante.pubkey()),
        &[licitante],
        cliente.get_recent_blockhash()?.0,
    );

    cliente.send_and_confirm_transaction(&transação)?;
    Ok(())
}

Conclusão

Nesta aula, cobrimos como implementar um sistema de leilão simples na Solana usando Rust. Definimos a estrutura do leilão, escrevemos os métodos do contrato inteligente para criar e fazer lances em leilões e, finalmente, configuramos uma função do lado do cliente para interagir com o programa de leilão.

Sinta-se à vontade para expandir este sistema de leilão adicionando recursos como cancelar leilões, lidar com lances de forma mais complexa ou armazenar histórico de lances. Boa codificação!

Did you like this article? Rate it from 1 to 5:

Thank you for voting!