Stellar Wallet Kit - Integração Rápida

Construindo um Sistema de Gerenciamento de Carteiras Stellar

Este guia irá orientá-lo na criação de um sistema completo de gerenciamento de carteiras para integração com a blockchain Stellar em sua aplicação React/Next.js. O sistema fornece conexão segura de carteira, desconexão e gerenciamento de estado com persistência.

Visão geral

O sistema consiste em três componentes principais:

  1. Provedor de Carteira - Gerenciamento de estado global para informações da carteira

  2. Hook de Carteira - Lógica de negócio para operações da carteira

  3. Configuração do Kit de Carteiras - Configuração de integração com a blockchain Stellar

Passo 1: Instalar Dependências

Primeiro, instale o pacote necessário Stellar Wallet Kit:

npm install @creit.tech/stellar-wallets-kit

Passo 2: Configure o Stellar Wallet Kit

Crie um arquivo de configuração que configure o Stellar Wallet Kit com suporte para múltiplos tipos de carteira:

import {
  StellarWalletsKit,
  WalletNetwork,
  FREIGHTER_ID,
  AlbedoModule,
  FreighterModule,
} from "@creit.tech/stellar-wallets-kit";

/**
 * Configuração principal para o Stellar Wallet Kit
 * Este kit suporta múltiplos tipos de carteira incluindo Freighter e Albedo
 * Configure para TESTNET durante o desenvolvimento e MAINNET para produção
 */
export const kit: StellarWalletsKit = new StellarWalletsKit({
  network: WalletNetwork.TESTNET,
  selectedWalletId: FREIGHTER_ID,
  modules: [new FreighterModule(), new AlbedoModule()],
});

/**
 * Interface para parâmetros de assinatura de transação
 */
interface signTransactionProps {
  unsignedTransaction: string;
  address: string;
}

/**
 * Assine uma transação Stellar usando a carteira conectada
 * Esta função lida com o processo de assinatura e retorna a transação assinada
 * 
 * @param unsignedTransaction - A string XDR da transação não assinada
 * @param address - O endereço da carteira que irá assinar a transação
 * @returns Promise<string> - O XDR da transação assinada
 */
export const signTransaction = async ({
  unsignedTransaction,
  address,
}: signTransactionProps): Promise<string> => {
  const { signedTxXdr } = await kit.signTransaction(unsignedTransaction, {
    address,
    networkPassphrase: WalletNetwork.TESTNET,
  });

  return signedTxXdr;
};

Passo 3: Crie o Provedor de Contexto da Carteira

O Wallet Provider gerencia o estado global da carteira e persiste informações no localStorage para uma melhor experiência do usuário

"use client";

import {
  createContext,
  useContext,
  useState,
  useEffect,
  ReactNode,
} from "react";

/**
 * Definição de tipo para o contexto da carteira
 * Contém endereço da carteira, nome e funções para gerenciar o estado da carteira
 */
type WalletContextType = {
  walletAddress: string | null;
  walletName: string | null;
  setWalletInfo: (address: string, name: string) => void;
  clearWalletInfo: () => void;
};

/**
 * Crie o contexto React para gerenciamento do estado da carteira
 */
const WalletContext = createContext<WalletContextType | undefined>(undefined);

/**
 * Componente Wallet Provider que envolve a aplicação
 * Gerencia o estado da carteira e fornece informações da carteira aos componentes filhos
 * Carrega automaticamente informações salvas da carteira do localStorage na inicialização
 */
export const WalletProvider = ({ children }: { children: ReactNode }) => {
  const [walletAddress, setWalletAddress] = useState<string | null>(null);
  const [walletName, setWalletName] = useState<string | null>(null);

  /**
   * Carregar informações salvas da carteira do localStorage quando o componente monta
   * Isso garante que o estado da carteira persista entre sessões do navegador
   */
  useEffect(() => {
    const storedAddress = localStorage.getItem("walletAddress");
    const storedName = localStorage.getItem("walletName");

    if (storedAddress) setWalletAddress(storedAddress);
    if (storedName) setWalletName(storedName);
  }, []);

  /**
   * Defina informações da carteira e salve-as no localStorage
   * Esta função é chamada quando uma carteira é conectada com sucesso
   * 
   * @param address - O endereço público da carteira
   * @param name - O nome/identificador da carteira (por exemplo, "Freighter", "Albedo")
   */
  const setWalletInfo = (address: string, name: string) => {
    setWalletAddress(address);
    setWalletName(name);
    localStorage.setItem("walletAddress", address);
    localStorage.setItem("walletName", name);
  };

  /**
   * Limpar informações da carteira e removê-las do localStorage
   * Esta função é chamada ao desconectar uma carteira
   */
  const clearWalletInfo = () => {
    setWalletAddress(null);
    setWalletName(null);
    localStorage.removeItem("walletAddress");
    localStorage.removeItem("walletName");
  };

  return (
    <WalletContext.Provider
      value={{ walletAddress, walletName, setWalletInfo, clearWalletInfo }}
    >
      {children}
    </WalletContext.Provider>
  );
};

/**
 * Hook personalizado para acessar o contexto da carteira
 * Fornece estado da carteira e funções para os componentes
 * Lança um erro se usado fora do WalletProvider
 */
export const useWalletContext = () => {
  const context = useContext(WalletContext);
  if (!context) {
    throw new Error("useWalletContext must be used within WalletProvider");
  }
  return context;
};

Passo 4: Crie o Hook da Carteira

O hook da carteira encapsula toda a lógica de negócio para operações da carteira, fornecendo uma interface limpa para os componentes:

import { kit } from "@/config/wallet-kit";
import { useWalletContext } from "@/providers/wallet.provider";
import { ISupportedWallet } from "@creit.tech/stellar-wallets-kit";

/**
 * Hook personalizado que fornece funcionalidade de conexão e desconexão de carteira
 * Integra-se com o Stellar Wallet Kit e gerencia o estado da carteira através do contexto
 */
export const useWallet = () => {
  // Obtenha funções de gerenciamento de carteira a partir do contexto
  const { setWalletInfo, clearWalletInfo } = useWalletContext();

  /**
   * Conectar a uma carteira Stellar usando o Wallet Kit
   * Abre um modal para seleção da carteira e lida com o processo de conexão
   * Define automaticamente as informações da carteira no contexto após conexão bem-sucedida
   */
  const connectWallet = async () => {
    await kit.openModal({
      modalTitle: "Conecte-se à sua carteira favorita",
      onWalletSelected: async (option: ISupportedWallet) => {
        // Defina a carteira selecionada como a carteira ativa
        kit.setWallet(option.id);

        // Obtenha o endereço e o nome da carteira
        const { address } = await kit.getAddress();
        const { name } = option;

        // Armazene informações da carteira no contexto e no localStorage
        setWalletInfo(address, name);
      },
    });
  };

  /**
   * Desconectar da carteira atual
   * Remove informações da carteira do contexto e do localStorage
   * Desconecta a carteira do Stellar Wallet Kit
   */
  const disconnectWallet = async () => {
    await kit.disconnect();
    clearWalletInfo();
  };

  /**
   * Lidar com a conexão da carteira com tratamento de erros
   * Envolve a função connectWallet em um bloco try-catch para melhor gerenciamento de erros
   */
  const handleConnect = async () => {
    try {
      await connectWallet();
    } catch (error) {
      console.error("Erro ao conectar a carteira:", error);
      // Você pode adicionar tratamento de erro adicional aqui, como mostrar notificações ao usuário
    }
  };

  /**
   * Lidar com a desconexão da carteira com tratamento de erros
   * Envolve a função disconnectWallet em um bloco try-catch para melhor gerenciamento de erros
   */
  const handleDisconnect = async () => {
    try {
      await disconnectWallet();
    } catch (error) {
      console.error("Erro ao desconectar a carteira:", error);
      // Você pode adicionar tratamento de erro adicional aqui, como mostrar notificações ao usuário
    }
  };

  return {
    connectWallet,
    disconnectWallet,
    handleConnect,
    handleDisconnect,
  };
};

Passo 5: Integre o Provider em Sua App

Envolva sua aplicação com o WalletProvider para habilitar o gerenciamento de estado da carteira por toda a sua app:

import { WalletProvider } from "@/providers/wallet.provider";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <WalletProvider>
          {children}
        </WalletProvider>
      </body>
    </html>
  );
}

Passo 6: Use o Hook da Carteira em Componentes

Agora você pode usar a funcionalidade da carteira em qualquer componente. Aqui está um exemplo de um botão de conexão de carteira:

import { useWallet } from "@/hooks/wallet.hook";
import { useWalletContext } from "@/providers/wallet.provider";

/**
 * Componente de botão de conexão/desconexão de carteira
 * Mostra diferentes estados com base no status de conexão da carteira
 */
export const WalletButton = () => {
  const { handleConnect, handleDisconnect } = useWallet();
  const { walletAddress, walletName } = useWalletContext();

  // Se a carteira estiver conectada, mostrar opção de desconectar
  if (walletAddress) {
    return (
      <div className="flex items-center gap-4">
        <div className="text-sm">
          <p className="font-medium">Conectado: {walletName}</p>
          <p className="text-gray-500">{walletAddress}</p>
        </div>
        <button 
          onClick={handleDisconnect}
          className="px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600"
        >
          Desconectar
        </button>
      </div>
    );
  }

  // Se a carteira não estiver conectada, mostrar opção de conectar
  return (
    <button 
      onClick={handleConnect}
      className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
    >
      Conectar Carteira
    </button>
  );
};

Principais Recursos e Benefícios

Persistência de Estado

  • As informações da carteira são automaticamente salvas no localStorage

  • Os usuários não precisam reconectar sua carteira toda vez que visitam sua app

  • Experiência do usuário sem atrito entre sessões do navegador

Suporte a Múltiplas Carteiras

  • Suporta múltiplos tipos de carteiras Stellar (Freighter, Albedo, etc.)

  • Fácil adicionar novos módulos de carteira conforme eles se tornem disponíveis

  • Os usuários podem escolher sua carteira preferida

Tratamento de Erros

  • Tratamento de erros abrangente para operações de carteira

  • Alternativas elegantes quando as operações de carteira falham

  • Fácil de estender com notificações de erro personalizadas

Segurança de Tipos

  • Suporte completo a TypeScript com definições de tipo apropriadas

  • Suporte a IntelliSense para melhor experiência de desenvolvimento

  • Verificação de erros em tempo de compilação para operações da carteira

Arquitetura Baseada em Contexto

  • Separação limpa de responsabilidades entre gerenciamento de estado e lógica de negócio

  • Fácil acesso ao estado da carteira a partir de qualquer componente

  • Gerenciamento centralizado do estado da carteira

Opções de Configuração

Seleção de Rede

  • TESTNET: Use durante desenvolvimento e testes

  • MAINNET: Use para aplicações de produção

Atualizado

Isto foi útil?