@trustless-work/blocks
v1.1.4
Published
<p align="center"> <img src="https://github.com/user-attachments/assets/5b182044-dceb-41f5-acf0-da22dea7c98a" alt="Trustless Work Blocks" /> </p>
Maintainers
Readme
Trustless Work React Blocks
Production‑ready React blocks for integrating Trustless Work's escrow and dispute resolution flows into your dApp.
It includes:
- UI blocks (cards, tables, dialogs, forms) to list and manage escrows
- Providers for API config, wallet context, dialogs and amount calculations
- TanStack Query hooks for fetching and mutating escrows
- Wallet‑kit helpers and error handling utilities
Requirements
- Node.js
>= 18.17 - React 18 / Next.js 13+ (App Router recommended)
Installation
npm install @trustless-work/blocks
# or
yarn add @trustless-work/blocks
# Then run the CLI to scaffold UI and providers
npx trustless-work initWhat init does:
- Installs shadcn/ui components (prompted)
- Installs required deps:
@tanstack/react-query,@trustless-work/escrow,axios,zod,react-hook-form,@creit.tech/stellar-wallets-kit,react-day-picker, etc. - Creates
.twblocks.jsonwith your UI base alias (default:"@/components/ui") - Optionally wires providers into your Next.js
app/layout.tsx
Environment:
- Create
NEXT_PUBLIC_API_KEYin your env. The library usesTrustlessWorkProviderwith thedevelopmentbase URL by default.
For a full walkthrough and screenshots, check the tutorial at the backoffice landing.
Quick Start
- Initialize
npx trustless-work init- Add providers (if you skipped wiring during init)
npx trustless-work add providers- Wrap your Next.js layout
// app/layout.tsx
import { ReactQueryClientProvider } from "@/components/tw-blocks/providers/ReactQueryClientProvider";
import { TrustlessWorkProvider } from "@/components/tw-blocks/providers/TrustlessWork";
import { EscrowProvider } from "@/components/tw-blocks/providers/EscrowProvider";
import { WalletProvider } from "@/components/tw-blocks/wallet-kit/WalletProvider";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<ReactQueryClientProvider>
<TrustlessWorkProvider>
<WalletProvider>
<EscrowProvider>{children}</EscrowProvider>
</WalletProvider>
</TrustlessWorkProvider>
</ReactQueryClientProvider>
</body>
</html>
);
}- Add a wallet button to your header
npx trustless-work add wallet-kit// Example usage
import { WalletButton } from "@/components/tw-blocks/wallet-kit/WalletButtons";
export function Header() {
return (
<div className="flex justify-end p-4">
<WalletButton />
</div>
);
}- List escrows quickly
# By role
npx trustless-work add escrows/escrows-by-role/cards
# Or table view
npx trustless-work add escrows/escrows-by-role/table// app/escrows/page.tsx
import { EscrowsByRoleCards } from "@/components/tw-blocks/escrows/escrows-by-role/cards/EscrowsCards";
import { EscrowDialogsProvider } from "@/components/tw-blocks/providers/EscrowDialogsProvider";
export default function Page() {
return (
<EscrowDialogsProvider>
<EscrowsByRoleCards />
</EscrowDialogsProvider>
);
}State Management Integration
This library works with any state solution. It exposes React Context providers and TanStack Query hooks. You can also integrate the hooks into Redux/Zustand if needed.
With TanStack Query (Recommended)
// Fetch escrows by role
import { useEscrowsByRoleQuery } from "@/components/tw-blocks/tanstack/useEscrowsByRoleQuery";
export function MyEscrows({ roleAddress }: { roleAddress: string }) {
const { data, isLoading, isError, refetch } = useEscrowsByRoleQuery({
role: "approver",
roleAddress,
isActive: true,
validateOnChain: true,
page: 1,
orderBy: "createdAt",
orderDirection: "desc",
});
if (isLoading) return <p>Loading…</p>;
if (isError) return <button onClick={() => refetch()}>Retry</button>;
return <pre>{JSON.stringify(data, null, 2)}</pre>;
}
// Mutations (deploy/fund/update/approve/change-status/release/dispute/resolve)
import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
export function DeployButton({ address }: { address: string }) {
const { deployEscrow } = useEscrowsMutations();
return (
<button
onClick={() =>
deployEscrow.mutate({
payload: {
/* InitializeSingleReleaseEscrowPayload */
},
type: "single-release",
address,
})
}
>
Deploy
</button>
);
}Available Blocks
To discover all available blocks, run:
npx trustless-work listScaffold top‑level groups
npx trustless-work add providers
npx trustless-work add wallet-kit
npx trustless-work add handle-errors
npx trustless-work add helpers
npx trustless-work add tanstack
npx trustless-work add escrowsEscrows by role
npx trustless-work add escrows/escrows-by-role
npx trustless-work add escrows/escrows-by-role/table
npx trustless-work add escrows/escrows-by-role/cardsEscrows by signer
npx trustless-work add escrows/escrows-by-signer
npx trustless-work add escrows/escrows-by-signer/table
npx trustless-work add escrows/escrows-by-signer/cardsEscrow details (optional standalone)
npx trustless-work add escrows/detailsSingle‑release flows
npx trustless-work add escrows/single-release
npx trustless-work add escrows/single-release/initialize-escrow
npx trustless-work add escrows/single-release/approve-milestone
npx trustless-work add escrows/single-release/change-milestone-status
npx trustless-work add escrows/single-release/fund-escrow
npx trustless-work add escrows/single-release/release-escrow
npx trustless-work add escrows/single-release/dispute-escrow
npx trustless-work add escrows/single-release/resolve-dispute
npx trustless-work add escrows/single-release/update-escrowEscrows UI summary
- Cards and tables to browse escrows (by role or by signer) with filters, pagination, and sorting
- Detail dialog with actions gated by roles and escrow flags
- Dialogs/forms for the single‑release lifecycle (initialize, fund, approve, change status, release, dispute, resolve, update)
Using cards (by role):
import { EscrowDialogsProvider } from "@/components/tw-blocks/providers/EscrowDialogsProvider";
import { EscrowsByRoleCards } from "@/components/tw-blocks/escrows/escrows-by-role/cards/EscrowsCards";
export default function Screen() {
return (
<EscrowDialogsProvider>
<EscrowsByRoleCards />
</EscrowDialogsProvider>
);
}Configuration Checklist
Make sure to:
Set
NEXT_PUBLIC_API_KEYand run the app against the correct environment (the provider defaults todevelopment).Configure your UI base imports. The CLI uses
.twblocks.jsonuiBaseto replace__UI_BASE__.
If your UI alias differs, pass--ui-base:npx trustless-work add escrows/escrows-by-role/cards --ui-base "@/components/ui"Wrap your app with all providers in this order:
ReactQueryClientProvider → TrustlessWorkProvider → WalletProvider → EscrowProvider
Best Practices
Providers
ReactQueryClientProvider: global query cache and devtools.TrustlessWorkProvider: sets APIbaseURLandapiKeyviaTrustlessWorkConfigfrom@trustless-work/escrow.WalletProvider: minimal wallet state (address/name) persisted in localStorage; used by wallet button and mutations.EscrowProvider: holds the currently selected escrow and roles; persisted in localStorage.EscrowDialogsProvider: centralizes dialog open/close state for escrow UI.EscrowAmountProvider: computes receiver/platform/fee splits for releases.
Queries and caching
- Use provided queries:
useEscrowsByRoleQuery,useEscrowsBySignerQuery. - All mutations invalidate
['escrows']automatically.
- Use provided queries:
Error handling
- Use
handleError(error)fromhandle-errors/handle.tsto map Axios and wallet errors to normalized types (ApiErrorTypes).
import { handleError } from "@/components/tw-blocks/handle-errors/handle"; try { /* ... */ } catch (e) { const err = handleError(e as any); /* show toast */ }- Use
Wallet-kit
WalletButtonopens a modal using@creit.tech/stellar-wallets-kitand stores address/name inWalletProvider.signTransaction({ unsignedTransaction, address })signs and returns XDR used by mutations.trustlinesandtrustlineOptionsinclude common assets for testnet/mainnet.
Env and network
- Use
development(default) ormainNetfrom@trustless-work/escrowinTrustlessWorkProvider. - Keep your API key in env and never commit it.
- Use
Contributing
We welcome contributions! Please open an issue or pull request in the repository and make sure to follow any existing contributing guidelines.
License
MIT License – see the LICENSE file for details.
