# Ciclo de vida de liberación única

Guía paso a paso para implementar el ciclo de vida de Liberación Única de Escrow

Importante

No funciona para un caso de uso real, solo para fines de prueba. Pero si quieres implementarlo, puedes usar el código a continuación como referencia y personalizarlo según tus necesidades.

### Crear un proyecto Next.js# <a href="#create-nextjs-project" id="create-nextjs-project"></a>

Comienza creando un nuevo proyecto Next.js con TypeScript y Tailwind CSS. Para facilitar la configuración, por favor usa el alias de ruta con "@/":

```
npx create-next-app@latest
```

Navega al directorio de tu proyecto:

```
cd my-trustless-app
```

### Instalar Trustless Work Blocks# <a href="#install-trustless-work-blocks" id="install-trustless-work-blocks"></a>

Instala el paquete principal de la librería:

npm

```
npm install @trustless-work/blocks
```

#### Ejecutar la configuración del CLI <a href="#run-cli-setup" id="run-cli-setup"></a>

Inicializa tu proyecto con el CLI de Trustless Work:

```
npx trustless-work init
```

Lo que hace el comando init:

* Instala componentes shadcn/ui (con indicaciones interactivas)
* Instala dependencias requeridas: @tanstack/react-query, @trustless-work/escrow, axios, zod, react-hook-form, @creit.tech/stellar-wallets-kit, react-day-picker, etc.
* Crea `.twblocks.json` archivo de configuración
* Opcionalmente conecta providers en tu Next.js `app/layout.tsx`

### Configuración del entorno <a href="#environment-configuration" id="environment-configuration"></a>

[Documentación](https://docs.trustlesswork.com/trustless-work/developer-resources/authentication/request-api-key)

Crear un `.env` archivo en la raíz de tu proyecto:

.env

```
# Requerido: Tu clave de API de Trustless Work 
NEXT_PUBLIC_API_KEY=your_api_key_here
```

### Agregar conectividad de billetera <a href="#add-wallet-connectivity" id="add-wallet-connectivity"></a>

Agrega conectividad de billetera a tu app:

```
npx trustless-work add wallet-kit
```

#### Envuelve tu app con WalletProvider: <a href="#wrap-app-wallet-provider" id="wrap-app-wallet-provider"></a>

Envuelve tu app con WalletProvider en tu layout.tsx:

app/layout.tsx

```
return (
    <WalletProvider>{children}</WalletProvider> 
);
```

#### Ejemplo de uso en una página: <a href="#example-usage-wallet-page" id="example-usage-wallet-page"></a>

Agrega conectividad de billetera a tu app:

app/page.tsx

```
"use client";

import { WalletButton } from "@/components/tw-blocks/wallet-kit/WalletButtons";

export default function Home() {
  return (
    <div className="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20">
      <header className="flex justify-between items-center w-full">
        <h2 className="text-2xl font-bold">Trustless Work</h2>

        {/* Botón de billetera */}
        <WalletButton />
      </header>
    </div>
  );
}
```

### Agregar helpers <a href="#add-helpers" id="add-helpers"></a>

Agrega helpers a tu app:

```
npx trustless-work add helpers
```

### Agregar Tanstack Query <a href="#add-tanstack-query" id="add-tanstack-query"></a>

Agrega Tanstack Query a tu app:

```
npx trustless-work add tanstack
```

### Agregar manejo de errores <a href="#add-handle-errors" id="add-handle-errors"></a>

Agrega manejo de errores a tu app:

```
npx trustless-work add handle-errors
```

### Agregar Providers (Si omitiste el comando init) <a href="#add-providers" id="add-providers"></a>

Agrega Providers a tu app:

```
npx trustless-work add providers
```

### Agregar componentes de Escrows Single Release <a href="#add-single-release-escrows" id="add-single-release-escrows"></a>

Agrega Single Release Escrows a tu app:

```
npx trustless-work add escrows/single-release
```

### Agregar componentes de Escrows Single-Multi Release <a href="#add-single-multi-release-escrows" id="add-single-multi-release-escrows"></a>

Agrega Single-Multi Release Escrows a tu app:

```
npx trustless-work add escrows/single-multi-release
```

### Agregar tarjetas Escrows por Rol <a href="#add-escrows-by-role-cards" id="add-escrows-by-role-cards"></a>

Agrega Escrows by Role Cards a tu app:

```
npx trustless-work add escrows/escrows-by-role/cards
```

#### Importar acciones <a href="#import-actions" id="import-actions"></a>

En el código, hay algunas acciones comentadas. Puedes descomentarlas e importarlas desde el bloque single-release. Ver las notas en los componentes escrows by role o by signer.

#### Código comentado <a href="#commented-out-code" id="commented-out-code"></a>

escrows/escrows-by-role/details/Actions.tsx

```
return (
    <div className="flex items-start justify-start flex-col gap-2 w-full">
      {/* Puedes agregar los botones aquí, usando los botones de los blocks. Estas acciones son condicionales según las banderas del escrow y los roles de usuario. */}
      {hasConditionalButtons && (
        <div className="flex flex-col gap-2 w-full">
          {/* El componente UpdateEscrowDialog debe renderizarse según el tipo de escrow. Significa que si selectedEscrow.type es "single-release", entonces debe renderizarse el componente UpdateEscrowDialog (del bloque single-release). Si selectedEscrow.type es "multi-release", entonces debe renderizarse el UpdateEscrowDialog (del bloque multi-release). */}
          {/* {shouldShowEditButton && <UpdateEscrowDialog />} */}

          {/* Funciona solo con escrows single-release */}
          {/* Solo aparece si el escrow tiene balance */}
          {/* {shouldShowDisputeButton && <DisputeEscrowButton />} */}

          {/* Funciona solo con escrows single-release */}
          {/* Solo aparece si el escrow está en disputa */}
          {/* {shouldShowResolveButton && <ResolveDisputeDialog />} */}

          {/* Funciona solo con escrows single-release */}
          {/* Solo aparece si todos los hitos están aprobados */}
          {/* {shouldShowReleaseFundsButton && <ReleaseEscrowButton />} */}
        </div>
      )}

      <FundEscrowDialog />
    </div>
  );
```

#### Acciones importadas <a href="#actions-imported" id="actions-imported"></a>

escrows/escrows-by-role/details/Actions.tsx

```
// Si necesitas ambos tipos, debes importar ambas versiones para actualizar el escrow
import { UpdateEscrowDialog } from "../../single-release/update-escrow/dialog/UpdateEscrow";
/* import { UpdateEscrowDialog as UpdateEscrowDialogMultiRelease } from "../../multi-release/update-escrow/dialog/UpdateEscrow"; */
import { FundEscrowDialog } from "../../single-multi-release/fund-escrow/dialog/FundEscrow";
import { DisputeEscrowButton } from "../../single-release/dispute-escrow/button/DisputeEscrow";
import { ResolveDisputeDialog } from "../../single-release/resolve-dispute/dialog/ResolveDispute";
import { ReleaseEscrowButton } from "../../single-release/release-escrow/button/ReleaseEscrow";

return (
    <div className="flex items-start justify-start flex-col gap-2 w-full">
      {/* Puedes agregar los botones aquí, usando los botones de los blocks. Estas acciones son condicionales según las banderas del escrow y los roles de usuario. */}
      {hasConditionalButtons && (
        <div className="flex flex-col gap-2 w-full">
          {/* El componente UpdateEscrowDialog debe renderizarse según el tipo de escrow. Significa que si selectedEscrow.type es "single-release", entonces debe renderizarse el componente UpdateEscrowDialog (del bloque single-release). Si selectedEscrow.type es "multi-release", entonces debe renderizarse el UpdateEscrowDialog (del bloque multi-release). */}
          {shouldShowEditButton && <UpdateEscrowDialog />}

          {/* Funciona solo con escrows single-release */}
          {shouldShowDisputeButton && <DisputeEscrowButton />}

          {/* Funciona solo con escrows single-release */}
          {shouldShowResolveButton && <ResolveDisputeDialog />}

          {/* Funciona solo con escrows single-release */}
          {shouldShowReleaseFundsButton && <ReleaseEscrowButton />}
        </div>
      )}

      <FundEscrowDialog />
    </div>
  );
```

### Configuración manual de Providers <a href="#manual-provider-setup" id="manual-provider-setup"></a>

Envuelve tu app con los providers requeridos en este orden específico:

app/layout.tsx

```
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import { ReactQueryClientProvider } from "@/components/tw-blocks/providers/ReactQueryClientProvider";
import { TrustlessWorkProvider } from "@/components/tw-blocks/providers/TrustlessWork";
import { WalletProvider } from "@/components/tw-blocks/wallet-kit/WalletProvider";
import { EscrowProvider } from "@/components/tw-blocks/providers/EscrowProvider";
import { EscrowDialogsProvider } from "@/components/tw-blocks/providers/EscrowDialogsProvider";
import { EscrowAmountProvider } from "@/components/tw-blocks/providers/EscrowAmountProvider";
import { Toaster } from "@/components/ui/sonner";

const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

const geistMono = Geist_Mono({
  variable: "--font-geist-mono",
  subsets: ["latin"],
});

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body
        // opcional: usa geistSans.variable y geistMono.variable
        className="antialiased"
      >
        <ReactQueryClientProvider>
          <TrustlessWorkProvider>
            <WalletProvider>
              <EscrowProvider>
                <EscrowDialogsProvider>
                  <EscrowAmountProvider>
                    {children}

                    <Toaster />
                  </EscrowAmountProvider>
                </EscrowDialogsProvider>
              </EscrowProvider>
            </WalletProvider>
          </TrustlessWorkProvider>
        </ReactQueryClientProvider>
      </body>
    </html>
  );
}
```

El orden de los providers importaLos providers deben anidarse en este orden exacto para un funcionamiento correcto.

### Ejemplo de uso en una página: <a href="#example-usage-complete-page" id="example-usage-complete-page"></a>

Ahora, puedes interactuar con todo el ciclo de vida del escrow.

app/page.tsx

```
"use client";

import { EscrowsByRoleCards } from "@/components/tw-blocks/escrows/escrows-by-role/cards/EscrowsCards";
import { InitializeEscrowDialog } from "@/components/tw-blocks/escrows/single-release/initialize-escrow/dialog/InitializeEscrow";
import { WalletButton } from "@/components/tw-blocks/wallet-kit/WalletButtons";

export default function Home() {
  return (
    <div className="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20">
      <header className="flex justify-between items-center w-full">
        <h2 className="text-2xl font-bold">Trustless Work</h2>
        <WalletButton />
      </header>
      <main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
        <div className="container">
          <div className="flex w-full mb-4 justify-end">
            <div className="flex w-1/6">
              <InitializeEscrowDialog />
            </div>
          </div>

          <EscrowsByRoleCards />
        </div>
      </main>
    </div>
  );
}

```

Todos los blocks fueron añadidos, ¡ahora úsalos!Ya tienes todos los blocks requeridos para comenzar a usar el ciclo de vida del escrow single-release.

### Interfaz final <a href="#final-ui" id="final-ui"></a>

Al usar estos componentes, podrás completar todo el ciclo de vida del escrow.

Consejo importante de uso- Estos componentes de tarjetas funcionan **por rol**. En la sección de filtros, puedes seleccionar el rol para el que deseas ver los escrows. En función de eso, se renderizarán los botones de acciones.\
\- Antes de empezar a usar la interfaz, debes agregar el **USDC** activo a tu billetera. Si no, no podrás interactuar con Trustless Work.

#### Diálogo de conexión de billetera <a href="#wallet-connection-dialog" id="wallet-connection-dialog"></a>

Mostrar el diálogo de conexión de billetera:

![Escrow Lifecycle](https://blocks.trustlesswork.com/_next/image?url=%2Fstart-from-scratch%2Fwallet-kit.png\&w=1080\&q=75)

#### Tarjetas por rol <a href="#cards-by-role" id="cards-by-role"></a>

Mostrar las tarjetas por rol:

![Escrow Lifecycle](https://blocks.trustlesswork.com/_next/image?url=%2Fstart-from-scratch%2Fcards-by-role.png\&w=2048\&q=75)

#### Diálogo de inicialización de escrow <a href="#initialize-escrow-dialog" id="initialize-escrow-dialog"></a>

Mostrar el diálogo de inicialización de escrow:

![Escrow Lifecycle](https://blocks.trustlesswork.com/_next/image?url=%2Fstart-from-scratch%2Finitialize-escrow.png\&w=2048\&q=75)

#### Diálogo de detalles del escrow <a href="#escrow-details-dialog" id="escrow-details-dialog"></a>

Mostrar el diálogo de detalles del escrow:

![Escrow Lifecycle](https://blocks.trustlesswork.com/_next/image?url=%2Fstart-from-scratch%2Fdetails.png\&w=2048\&q=75)

La forma más fácil de implementar escrows en blockchain."
