Stellar Wallet Kit - Integración rápida
Construyendo un Sistema de Gestión de Carteras Stellar
Esta guía te mostrará cómo crear un sistema integral de gestión de carteras para la integración con la blockchain Stellar en tu aplicación React/Next.js. El sistema ofrece conexión segura de carteras, desconexión y gestión de estado con persistencia.
Resumen
El sistema consta de tres componentes principales:
Proveedor de Carteras - Gestión global del estado para la información de la cartera
Hook de Cartera - Lógica de negocio para las operaciones de la cartera
Configuración del Kit de Carteras - Configuración de integración con la blockchain Stellar
Paso 1: Instalar dependencias
Primero, instala el paquete requerido del Stellar Wallet Kit:
npm install @creit.tech/stellar-wallets-kitPaso 2: Configurar el Stellar Wallet Kit
Crea un archivo de configuración que configure el Stellar Wallet Kit con soporte para múltiples tipos de cartera:
import {
StellarWalletsKit,
WalletNetwork,
FREIGHTER_ID,
AlbedoModule,
FreighterModule,
} from "@creit.tech/stellar-wallets-kit";
/**
* Configuración principal para el Stellar Wallet Kit
* Este kit admite múltiples tipos de carteras, incluyendo Freighter y Albedo
* Configurar para TESTNET durante el desarrollo y MAINNET para producción
*/
export const kit: StellarWalletsKit = new StellarWalletsKit({
network: WalletNetwork.TESTNET,
selectedWalletId: FREIGHTER_ID,
modules: [new FreighterModule(), new AlbedoModule()],
});
/**
* Interfaz para los parámetros de firma de transacciones
*/
interface signTransactionProps {
unsignedTransaction: string;
address: string;
}
/**
* Firmar una transacción Stellar usando la cartera conectada
* Esta función maneja el proceso de firma y devuelve la transacción firmada
*
* @param unsignedTransaction - La cadena XDR de la transacción sin firmar
* @param address - La dirección de la cartera que firmará la transacción
* @returns Promise<string> - El XDR de la transacción firmada
*/
export const signTransaction = async ({
unsignedTransaction,
address,
}: signTransactionProps): Promise<string> => {
const { signedTxXdr } = await kit.signTransaction(unsignedTransaction, {
address,
networkPassphrase: WalletNetwork.TESTNET,
});
return signedTxXdr;
};Paso 3: Crear el Proveedor de Contexto de la Cartera
El Proveedor de Carteras gestiona el estado global de la cartera y persiste la información en localStorage para una mejor experiencia de usuario
"use client";
import {
createContext,
useContext,
useState,
useEffect,
ReactNode,
} from "react";
/**
* Definición de tipos para el contexto de la cartera
* Contiene la dirección de la cartera, el nombre y funciones para gestionar el estado de la cartera
*/
type WalletContextType = {
walletAddress: string | null;
walletName: string | null;
setWalletInfo: (address: string, name: string) => void;
clearWalletInfo: () => void;
};
/**
* Crear el contexto de React para la gestión del estado de la cartera
*/
const WalletContext = createContext<WalletContextType | undefined>(undefined);
/**
* Componente Wallet Provider que envuelve la aplicación
* Gestiona el estado de la cartera y proporciona información de la cartera a los componentes hijos
* Carga automáticamente la información de la cartera guardada desde localStorage en la inicialización
*/
export const WalletProvider = ({ children }: { children: ReactNode }) => {
const [walletAddress, setWalletAddress] = useState<string | null>(null);
const [walletName, setWalletName] = useState<string | null>(null);
/**
* Cargar la información de la cartera guardada desde localStorage cuando el componente se monta
* Esto asegura que el estado de la cartera persista a través de las sesiones del navegador
*/
useEffect(() => {
const storedAddress = localStorage.getItem("walletAddress");
const storedName = localStorage.getItem("walletName");
if (storedAddress) setWalletAddress(storedAddress);
if (storedName) setWalletName(storedName);
}, []);
/**
* Establecer la información de la cartera y guardarla en localStorage
* Esta función se llama cuando una cartera se conecta con éxito
*
* @param address - La dirección pública de la cartera
* @param name - El nombre/identificador de la cartera (por ejemplo, "Freighter", "Albedo")
*/
const setWalletInfo = (address: string, name: string) => {
setWalletAddress(address);
setWalletName(name);
localStorage.setItem("walletAddress", address);
localStorage.setItem("walletName", name);
};
/**
* Borrar la información de la cartera y eliminarla de localStorage
* Esta función se llama al desconectar una cartera
*/
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 acceder al contexto de la cartera
* Proporciona el estado de la cartera y funciones a los componentes
* Lanza un error si se usa fuera de WalletProvider
*/
export const useWalletContext = () => {
const context = useContext(WalletContext);
if (!context) {
throw new Error("useWalletContext must be used within WalletProvider");
}
return context;
};Paso 4: Crear el Hook de la Cartera
El hook de la cartera encapsula toda la lógica de negocio para las operaciones de la cartera, proporcionando una interfaz limpia para los componentes:
import { kit } from "@/config/wallet-kit";
import { useWalletContext } from "@/providers/wallet.provider";
import { ISupportedWallet } from "@creit.tech/stellar-wallets-kit";
/**
* Hook personalizado que proporciona funcionalidad de conexión y desconexión de carteras
* Se integra con el Stellar Wallet Kit y gestiona el estado de la cartera a través del contexto
*/
export const useWallet = () => {
// Obtener funciones de gestión de cartera desde el contexto
const { setWalletInfo, clearWalletInfo } = useWalletContext();
/**
* Conectar a una cartera Stellar usando el Wallet Kit
* Abre un modal para la selección de cartera y maneja el proceso de conexión
* Establece automáticamente la información de la cartera en el contexto tras una conexión exitosa
*/
const connectWallet = async () => {
await kit.openModal({
modalTitle: "Conéctate a tu cartera favorita",
onWalletSelected: async (option: ISupportedWallet) => {
// Establecer la cartera seleccionada como la cartera activa
kit.setWallet(option.id);
// Obtener la dirección y el nombre de la cartera
const { address } = await kit.getAddress();
const { name } = option;
// Almacenar la información de la cartera en el contexto y en localStorage
setWalletInfo(address, name);
},
});
};
/**
* Desconectarse de la cartera actual
* Borra la información de la cartera del contexto y de localStorage
* Desconecta la cartera del Stellar Wallet Kit
*/
const disconnectWallet = async () => {
await kit.disconnect();
clearWalletInfo();
};
/**
* Manejar la conexión de la cartera con manejo de errores
* Envuelve la función connectWallet en un bloque try-catch para un mejor manejo de errores
*/
const handleConnect = async () => {
try {
await connectWallet();
} catch (error) {
console.error("Error connecting wallet:", error);
// Aquí puedes añadir manejo adicional de errores, como mostrar notificaciones al usuario
}
};
/**
* Manejar la desconexión de la cartera con manejo de errores
* Envuelve la función disconnectWallet en un bloque try-catch para un mejor manejo de errores
*/
const handleDisconnect = async () => {
try {
await disconnectWallet();
} catch (error) {
console.error("Error disconnecting wallet:", error);
// Aquí puedes añadir manejo adicional de errores, como mostrar notificaciones al usuario
}
};
return {
connectWallet,
disconnectWallet,
handleConnect,
handleDisconnect,
};
};Paso 5: Integrar el Proveedor en tu App
Envuelve tu aplicación con WalletProvider para habilitar la gestión del estado de la cartera en toda tu 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>
);
}Paso 6: Usar el Hook de Cartera en Componentes
Ahora puedes usar la funcionalidad de la cartera en cualquier componente. Aquí hay un ejemplo de un botón de conexión de cartera:
import { useWallet } from "@/hooks/wallet.hook";
import { useWalletContext } from "@/providers/wallet.provider";
/**
* Componente de botón para conectar/desconectar la cartera
* Muestra diferentes estados según el estado de conexión de la cartera
*/
export const WalletButton = () => {
const { handleConnect, handleDisconnect } = useWallet();
const { walletAddress, walletName } = useWalletContext();
// Si la cartera está conectada, mostrar la opción de desconexión
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>
);
}
// Si la cartera no está conectada, mostrar la opción de conexión
return (
<button
onClick={handleConnect}
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
>
Conectar Billetera
</button>
);
};Características clave y beneficios
Persistencia de estado
La información de la cartera se guarda automáticamente en localStorage
Los usuarios no necesitan reconectar su cartera cada vez que visitan tu app
Experiencia de usuario fluida a través de las sesiones del navegador
Soporte multi-cartera
Admite múltiples tipos de carteras Stellar (Freighter, Albedo, etc.)
Fácil de agregar nuevos módulos de cartera a medida que estén disponibles
Los usuarios pueden elegir su cartera preferida
Manejo de errores
Manejo de errores integral para las operaciones de cartera
Recuperaciones elegantes cuando las operaciones de cartera fallan
Fácil de extender con notificaciones de error personalizadas
Seguridad de tipos
Soporte completo de TypeScript con definiciones de tipos adecuadas
Soporte de IntelliSense para una mejor experiencia de desarrollo
Verificación de errores en tiempo de compilación para las operaciones de cartera
Arquitectura basada en contexto
Separación clara de responsabilidades entre la gestión del estado y la lógica de negocio
Fácil acceso al estado de la cartera desde cualquier componente
Gestión centralizada del estado de la cartera
Opciones de configuración
Selección de red
TESTNET: Usar durante el desarrollo y las pruebas
MAINNET: Usar para aplicaciones en producción
Última actualización
¿Te fue útil?