Skip to main content

@stwd/react

Drop-in React components for building agent management UIs. Includes wallet overview, transaction history, policy controls, approval queues, and spend analytics — all wired to the Steward API with zero configuration.

Install

npm install @stwd/react @stwd/sdk
# or: bun add @stwd/react @stwd/sdk

Quick Start

import { StewardProvider, WalletOverview, PolicyControls, TransactionHistory } from "@stwd/react";
import "@stwd/react/styles.css";
import { StewardClient } from "@stwd/sdk";

const client = new StewardClient({
  baseUrl: "https://api.steward.fi",
  apiKey: "your-tenant-key",
  tenantId: "your-tenant-id",
});

function AgentDashboard({ agentId }: { agentId: string }) {
  return (
    <StewardProvider client={client} agentId={agentId}>
      <WalletOverview showQR />
      <PolicyControls />
      <TransactionHistory pageSize={10} />
    </StewardProvider>
  );
}

Provider

<StewardProvider>

Wraps all other Steward components. Must be a parent of any component that uses Steward hooks or components.
<StewardProvider
  client={client}        // StewardClient instance
  agentId="agent-1"     // The agent to display
  theme={{              // Optional theme overrides
    primaryColor: "#8B5CF6",
    colorScheme: "dark",
  }}
>
  {children}
</StewardProvider>
PropTypeRequiredDescription
clientStewardClientConfigured SDK client
agentIdstringAgent ID to scope all components to
themeThemeOverridesOverride default CSS custom properties

Components

<WalletOverview>

Displays the agent’s wallet address, on-chain balance, chain info, and optionally a funding QR code.
<WalletOverview
  showQR           // Show funding QR code
  showCopy         // Show copy-to-clipboard button (default: true)
  refreshInterval={30000}  // Auto-refresh balance every 30s
/>

<TransactionHistory>

Paginated transaction history with status badges and blockchain explorer links.
<TransactionHistory
  pageSize={10}    // Rows per page (default: 10)
  showFilters      // Show status/date filter controls
/>
Displays: timestamp, destination address, value (ETH), status badge (signed / pending_approval / rejected / failed), and a link to the block explorer.

<PolicyControls>

Human-friendly policy management UI. Shows the current policy set with toggles, limits, and address lists.
<PolicyControls
  readOnly    // Disable editing (default: false)
  showTemplates  // Show policy template selector
/>
Supports all policy types: spending-limit, approved-addresses, rate-limit, time-window, auto-approve-threshold. Respects the tenant’s policyExposure config — policies marked hidden or enforced are not shown.

<ApprovalQueue>

Shows pending transactions awaiting human review. Supports approve and deny actions.
<ApprovalQueue
  pollInterval={5000}   // Poll for new approvals every 5s (default: 5000ms)
  onApprove={(id) => console.log("Approved:", id)}
  onDeny={(id) => console.log("Denied:", id)}
/>
Each item shows the destination address, value, requesting agent, and time waiting. Approve/deny actions call the API immediately.

<SpendDashboard>

Spend analytics for the agent with budget bars and summary numbers.
<SpendDashboard
  range="week"   // "day" | "week" | "month" (default: "week")
/>
Shows: total spent in the selected range vs. the policy limit, daily breakdown chart, and largest single transactions.

Hooks

All components are built on public hooks — use them directly for custom UIs.
import {
  useSteward,
  useWallet,
  useTransactions,
  usePolicies,
  useApprovals,
  useSpend,
} from "@stwd/react";

useSteward()

Access the Steward context: client, agentId, theme, and tenant config.
const { client, agentId, theme, tenantConfig } = useSteward();

useWallet()

Agent identity and on-chain balance with auto-refresh.
const { agent, balance, isLoading, error, refresh } = useWallet();

// agent: AgentIdentity | null
// balance: { native: string; nativeFormatted: string; symbol: string; chainId: number } | null

useTransactions(opts?)

Paginated transaction history.
const { transactions, page, setPage, total, isLoading } = useTransactions({
  pageSize: 10,
  status: "all", // "all" | "signed" | "pending_approval" | "rejected"
});

usePolicies()

Current policy set with CRUD operations.
const { policies, setPolicies, isLoading, isSaving } = usePolicies();

// Update a spending limit
await setPolicies([
  ...policies,
  {
    id: "new-limit",
    type: "spending-limit",
    enabled: true,
    config: { maxPerTx: "100000000000000000", maxPerDay: "500000000000000000" },
  },
]);

useApprovals(interval?)

Pending approvals with approve/reject actions.
const { approvals, approve, deny, isLoading } = useApprovals(5000); // poll every 5s

// Approve a pending transaction
await approve(approvalId);

// Deny with a reason
await deny(approvalId, "Amount too large");

useSpend(range?)

Spend analytics for a time range.
const { spend, isLoading } = useSpend("week");

// spend: {
//   today: string; thisWeek: string; thisMonth: string;
//   todayFormatted: string; thisWeekFormatted: string; thisMonthFormatted: string;
// }

Theming

Components use CSS custom properties scoped to .stwd-root. Override any --stwd-* variable in your stylesheet:
.stwd-root {
  --stwd-primary: #8B5CF6;
  --stwd-accent: #A78BFA;
  --stwd-bg: #0F0F0F;
  --stwd-surface: #1A1A2E;
  --stwd-text: #FAFAFA;
  --stwd-muted: #6B7280;
  --stwd-success: #10B981;
  --stwd-error: #EF4444;
  --stwd-warning: #F59E0B;
  --stwd-radius: 12px;
  --stwd-font: Inter, system-ui, sans-serif;
}
Or pass overrides to the provider:
<StewardProvider
  client={client}
  agentId={agentId}
  theme={{
    primaryColor: "#FF6B35",
    accentColor: "#FF8C5A",
    backgroundColor: "#0A0A0A",
    colorScheme: "dark",
  }}
>
The tenant’s control plane config can also supply a theme — @stwd/react fetches it automatically from GET /tenants/:id/config and merges it with any prop overrides.

Tenant Control Plane Integration

If your Steward tenant has a control plane config configured, @stwd/react will automatically:
  • Hide or lock policies marked as hidden or enforced in policyExposure
  • Apply the tenant’s theme as base styles
  • Show/hide features based on featureFlags (e.g., showFundingQR, showApprovalQueue)
  • Use policy templates from policyTemplates in the policy editor
This lets platform operators white-label the UI and control what end users can configure.

Full Example

import React from "react";
import {
  StewardProvider,
  WalletOverview,
  TransactionHistory,
  PolicyControls,
  ApprovalQueue,
  SpendDashboard,
} from "@stwd/react";
import "@stwd/react/styles.css";
import { StewardClient } from "@stwd/sdk";

const client = new StewardClient({
  baseUrl: process.env.STEWARD_API_URL!,
  apiKey: process.env.STEWARD_API_KEY!,
  tenantId: process.env.STEWARD_TENANT_ID!,
});

export function AgentManagementPage({ agentId }: { agentId: string }) {
  return (
    <StewardProvider
      client={client}
      agentId={agentId}
      theme={{ colorScheme: "dark" }}
    >
      <div style={{ display: "grid", gap: 24, maxWidth: 960, margin: "0 auto" }}>
        <WalletOverview showQR showCopy />
        <SpendDashboard range="week" />
        <ApprovalQueue pollInterval={10000} />
        <PolicyControls showTemplates />
        <TransactionHistory pageSize={20} showFilters />
      </div>
    </StewardProvider>
  );
}

Peer Dependencies

  • react >= 18
  • react-dom >= 18
  • @stwd/sdk >= 0.3.0