Ciclo de Vida de Liberação Única da Caução
Guia passo a passo para implementar o ciclo de vida Single Release do Escrow
Importante
Não funciona para um caso de uso real, apenas para fins de teste. Mas se você quiser implementá-lo, pode usar o código abaixo como referência e personalizá-lo conforme suas necessidades.
Crie um projeto Next.js#
Comece criando um novo projeto Next.js com TypeScript e Tailwind CSS. Para facilitar a configuração, por favor use o alias de caminho com "@/":
npx create-next-app@latestNavegue até o diretório do seu projeto:
cd my-trustless-appInstale o Trustless Work Blocks#
Instale o pacote principal da biblioteca:
npm
npm install @trustless-work/blocksExecute o setup via CLI
Inicie seu projeto com o Trustless Work CLI:
npx trustless-work initO que o comando init faz:
Instala componentes shadcn/ui (com prompts interativos)
Instala dependências necessárias: @tanstack/react-query, @trustless-work/escrow, axios, zod, react-hook-form, @creit.tech/stellar-wallets-kit, react-day-picker, etc.
Cria
.twblocks.jsonarquivo de configuraçãoOpcionalmente conecta providers ao seu Next.js
app/layout.tsx
Configuração de Ambiente
Crie um .env arquivo na raiz do seu projeto:
.env
# Obrigatório: Sua chave de API do Trustless Work
NEXT_PUBLIC_API_KEY=your_api_key_hereAdicione Conectividade de Carteira
Adicione conectividade de carteira ao seu app:
npx trustless-work add wallet-kitEnvolva seu app com o WalletProvider:
Envolva seu app com o WalletProvider no seu layout.tsx:
app/layout.tsx
return (
<WalletProvider>{children}</WalletProvider>
);Exemplo de uso em uma página:
Adicione conectividade de carteira ao seu 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ão de Carteira */}
<WalletButton />
</header>
</div>
);
}Adicione Helpers
Adicione helpers ao seu app:
npx trustless-work add helpersAdicione Tanstack Query
Adicione Tanstack Query ao seu app:
npx trustless-work add tanstackAdicione Tratamento de Erros
Adicione Tratamento de Erros ao seu app:
npx trustless-work add handle-errorsAdicione Providers (se você pulou o comando init)
Adicione Providers ao seu app:
npx trustless-work add providersAdicione Componentes de Single Release Escrows
Adicione Single Release Escrows ao seu app:
npx trustless-work add escrows/single-releaseAdicione Componentes de Single-Multi Release Escrows
Adicione Single-Multi Release Escrows ao seu app:
npx trustless-work add escrows/single-multi-releaseAdicione Escrows por Cartões de Função
Adicione Escrows por Cartões de Função ao seu app:
npx trustless-work add escrows/escrows-by-role/cardsImporte Ações
No código, há algumas ações comentadas. Você pode descomentá-las e importá-las do bloco single-release. Veja as notas nos componentes escrows by role ou by signer.
Código Comentado
escrows/escrows-by-role/details/Actions.tsx
return (
<div className="flex items-start justify-start flex-col gap-2 w-full">
{/* Você pode adicionar os botões aqui, usando os botões dos blocks. Essas ações são condicionais com base nas flags do escrow e nas funções dos usuários. */}
{hasConditionalButtons && (
<div className="flex flex-col gap-2 w-full">
{/* O componente UpdateEscrowDialog deve ser renderizado com base no tipo do escrow. Isso significa que se selectedEscrow.type for "single-release", então o UpdateEscrowDialog (do bloco single-release) deve ser renderizado. Se selectedEscrow.type for "multi-release", então o UpdateEscrowDialog (do bloco multi-release) deve ser renderizado. */}
{/* {shouldShowEditButton && <UpdateEscrowDialog />} */}
{/* Funciona apenas com escrows single-release */}
{/* Aparece somente se o escrow tiver saldo */}
{/* {shouldShowDisputeButton && <DisputeEscrowButton />} */}
{/* Funciona apenas com escrows single-release */}
{/* Aparece somente se o escrow estiver em disputa */}
{/* {shouldShowResolveButton && <ResolveDisputeDialog />} */}
{/* Funciona apenas com escrows single-release */}
{/* Aparece somente se todos os marcos estiverem aprovados */}
{/* {shouldShowReleaseFundsButton && <ReleaseEscrowButton />} */}
</div>
)}
<FundEscrowDialog />
</div>
);Ações Importadas
escrows/escrows-by-role/details/Actions.tsx
// Se você precisar de ambos os tipos, deve importar ambas as versões para atualizar o 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">
{/* Você pode adicionar os botões aqui, usando os botões dos blocks. Essas ações são condicionais com base nas flags do escrow e nas funções dos usuários. */}
{hasConditionalButtons && (
<div className="flex flex-col gap-2 w-full">
{/* O componente UpdateEscrowDialog deve ser renderizado com base no tipo do escrow. Isso significa que se selectedEscrow.type for "single-release", então o UpdateEscrowDialog (do bloco single-release) deve ser renderizado. Se selectedEscrow.type for "multi-release", então o UpdateEscrowDialog (do bloco multi-release) deve ser renderizado. */}
{shouldShowEditButton && <UpdateEscrowDialog />}
{/* Funciona apenas com escrows single-release */}
{shouldShowDisputeButton && <DisputeEscrowButton />}
{/* Funciona apenas com escrows single-release */}
{shouldShowResolveButton && <ResolveDisputeDialog />}
{/* Funciona apenas com escrows single-release */}
{shouldShowReleaseFundsButton && <ReleaseEscrowButton />}
</div>
)}
<FundEscrowDialog />
</div>
);Configuração Manual de Providers
Envolva seu app com os providers requeridos nesta ordem específica:
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: use geistSans.variable e geistMono.variable
className="antialiased"
>
<ReactQueryClientProvider>
<TrustlessWorkProvider>
<WalletProvider>
<EscrowProvider>
<EscrowDialogsProvider>
<EscrowAmountProvider>
{children}
<Toaster />
</EscrowAmountProvider>
</EscrowDialogsProvider>
</EscrowProvider>
</WalletProvider>
</TrustlessWorkProvider>
</ReactQueryClientProvider>
</body>
</html>
);
}A ordem dos providers importaOs providers devem ser aninhados nesta ordem exata para o funcionamento correto.
Exemplo de uso em uma página:
Agora, você pode interagir com todo o ciclo de vida do 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 os blocks foram adicionados, agora use-os!Você já tem todos os blocks necessários para começar a usar o ciclo de vida do escrow single-release.
UI Final
Usando esses componentes, você será capaz de completar todo o ciclo de vida do escrow.
Conselho importante de uso- Esses componentes de cards funcionam por função. Na seção de filtros, você pode selecionar a função para a qual deseja ver os escrows. Com base nisso, os botões de ação serão renderizados. - Antes de começar a usar a UI, você deve adicionar o USDC ativo à sua carteira. Caso contrário, você não poderá interagir com o Trustless Work.
Diálogo de Conexão de Carteira
Mostre o diálogo de conexão de carteira:

Cartões por Função
Mostre os cartões por função:

Diálogo de Inicialização de Escrow
Mostre o diálogo de inicialização de escrow:

Diálogo de Detalhes do Escrow
Mostre o diálogo de detalhes do escrow:

A maneira mais fácil de implementar escrows em blockchain."
Atualizado
Isto foi útil?