# Servicios

## Resumen

Con el fin de tener un código de buena calidad y limpio, hemos generado un servicio genérico que interactúa con Trustless Work.

## Servicio genérico de escrow

Cada respuesta y payload están completamente tipados con las entidades que habíamos definido antes.

```typescript
import http from "@/config/axios";
import { AxiosError } from "axios";
import { signTransaction } from "../../auth/helpers/stellar-wallet-kit.helper";
import { handleError } from "@/errors/utils/handle-errors";
import { WalletError } from "@/@types/errors.entity";
import { kit } from "@/config/wallet-kit";
import { EscrowRequestResponse } from "@/@types/escrows/escrow-response.entity";
import { EscrowPayloadService } from "@/@types/escrows/escrow-payload.entity";
import { Escrow } from "@/@types/escrows/escrow.entity";
import { HttpMethod } from "@/@types/http.entity";

// Interfaz que define las propiedades requeridas para las operaciones del servicio de escrow
interface EscrowServiceProps<T extends EscrowPayloadService> {
  payload: T;
  endpoint: string;
  method: HttpMethod;
  requiresSignature?: boolean;
  returnEscrowDataIsRequired?: boolean;
}

/**
 * La clase EscrowService maneja todas las operaciones relacionadas con escrow
 * incluidos la firma de transacciones y el envío a la red Stellar
 */
export class EscrowService {
  private static instance: EscrowService;

  private constructor() {}

  /**
   * Obtener la instancia singleton de EscrowService
   */
  public static getInstance(): EscrowService {
    if (!EscrowService.instance) {
      EscrowService.instance = new EscrowService();
    }
    return EscrowService.instance;
  }

  /**
   * Manejar solicitudes GET que no requieren firma
   */
  private async handleGetRequest<T extends EscrowPayloadService>(
    endpoint: string,
    payload: T
  ): Promise<EscrowRequestResponse> {
    const { data } = await http.get<EscrowRequestResponse>(endpoint, {
      params: payload,
    });
    return data;
  }

  /**
   * Obtener la dirección de la wallet para la firma de la transacción
   */
  private async getWalletAddress(): Promise<string> {
    const { address } = await kit.getAddress();
    return address;
  }

  /**
   * Firmar la transacción usando la wallet
   */
  private async signTransactionWithWallet(
    unsignedTransaction: string,
    address: string
  ): Promise<string> {
    // Firmar la transacción usando el Stellar Wallet Kit
    return await signTransaction({ unsignedTransaction, address });
  }

  /**
   * Enviar la transacción firmada a la red
   */
  private async sendSignedTransaction(
    signedXdr: string,
    returnEscrowDataIsRequired: boolean
  ): Promise<EscrowRequestResponse> {
    const tx = await http.post("/helper/send-transaction", {
      signedXdr,
      returnEscrowDataIsRequired,
    });
    return tx.data;
  }

  /**
   *
   * Método principal para manejar las operaciones de escrow
   *
   * @Reference URL: https://surli.cc/rlyqso
   *
   * @Flow:
   * 1. Obtener la dirección de la wallet
   * 2. Hacer la solicitud inicial para obtener [transacción sin firmar]
   * 3. [Firmar la transacción] con la wallet
   * 4. Enviar la [transacción firmada] a la red
   * 5. Devolver [datos del escrow]
   *
   * @Nota:
   * - Este método maneja tanto solicitudes GET como POST
   * - También maneja la firma de transacciones
   * - Devuelve los datos del escrow si se requieren
   * - Maneja tanto errores HTTP como de Wallet
   *
   */
  public async execute<T extends EscrowPayloadService>({
    payload,
    endpoint,
    method,
    requiresSignature = true,
    returnEscrowDataIsRequired = true,
  }: EscrowServiceProps<T>): Promise<EscrowRequestResponse | Escrow> {
    try {
      // Manejar solicitudes GET que no requieren firma
      if (!requiresSignature && method === "get") {
        return await this.handleGetRequest(endpoint, payload);
      }

      // Obtener la dirección de la wallet y hacer la solicitud inicial
      const address = await this.getWalletAddress();
      const response = await http[method]<EscrowRequestResponse>(
        endpoint,
        payload
      );

      const { unsignedTransaction } = response.data;

      // Validar que recibimos una transacción sin firmar
      if (!unsignedTransaction) {
        throw new Error("No unsigned transaction received from the server");
      }

      // Firmar y enviar la transacción
      const signedTxXdr = await this.signTransactionWithWallet(
        unsignedTransaction,
        dirección
      );

      // Enviar la transacción firmada a la red
      return await this.sendSignedTransaction(
        signedTxXdr,
        returnEscrowDataIsRequired
      );
    } catch (error: unknown) {
      const mappedError = handleError(error as AxiosError | WalletError);
      console.error("Error:", mappedError.message);
      throw new Error(mappedError.message);
    }
  }
}

// Exportar una instancia singleton para un acceso fácil
export const escrowService = EscrowService.getInstance();

```

Este servicio será usado en los hooks personalizados donde enviamos envíos con los formularios adaptados a cada endpoint de Trustless Work.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.trustlesswork.com/trustless-work/v1-es/dapps-oss/escrow-lab/servicios.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
