> ## Documentation Index
> Fetch the complete documentation index at: https://spiceflow-docs.spicenet.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Hooks

> React hooks for building custom UIs with Spice Flow

These hooks let you build custom UIs on top of the Spice Flow SDK. If the prebuilt components don't fit your use case, use these hooks to access wallet state, balances, and execution directly.

## useSpiceExecution

The core execution hook. Handles EIP 7702 delegation signing, intent submission, and solver execution polling. This is what powers `SpiceDeposit` under the hood.

### Usage

```tsx theme={null}
import { useSpiceExecution } from "@spicenet-io/spiceflow-ui";

function CustomDeposit() {
  const { executeGasless } = useSpiceExecution();

  const handleExecute = async () => {
    const actionId = await executeGasless(
      chainBatches,           // destination chain calls
      tokenAddress,           // token being deposited
      tokenTransferAmount,    // amount in wei
      (progress) => {         // progress callback
        console.log(progress.step, progress.message);
      },
    );
    console.log("Action completed:", actionId);
  };

  return <button onClick={handleExecute}>Execute</button>;
}
```

### Return Value

```typescript theme={null}
{
  executeGasless: (
    chainBatches: ChainBatch[],
    tokenAddress: string,
    tokenTransferAmount: bigint,
    onProgress?: (progress: GaslessProgress) => void,
    signal?: AbortSignal,
    options?: GaslessExecutionOptions,
  ) => Promise<string>  // returns actionId
}
```

### Progress Steps

The `onProgress` callback receives updates as execution proceeds:

| Step                 | Description                      |
| -------------------- | -------------------------------- |
| `idle`               | Not started                      |
| `building`           | Building the intent              |
| `signing-delegation` | User signing EIP 7702 delegation |
| `signing-intent`     | User signing the intent hash     |
| `submitting`         | Submitting to the solver         |
| `executing`          | Solver executing on chain        |
| `success`            | Execution complete               |
| `error`              | Something went wrong             |

***

## useSpiceAssets

Fetch the user's Spice balance from the relayer API. This returns the off chain balance (what the user has deposited via escrow), not on chain wallet balances.

### Usage

```tsx theme={null}
import { useSpiceAssets } from "@spicenet-io/spiceflow-ui";

function BalanceDisplay() {
  const { assets, loading, hasBalance, refetch, getAssetsByChain } = useSpiceAssets({
    address: "0x...",
    supportedChains: [8453, 4114],
    refetchInterval: 30000,
  });

  if (loading) return <p>Loading...</p>;
  if (!hasBalance) return <p>No deposits yet</p>;

  return (
    <ul>
      {assets.map(asset => (
        <li key={`${asset.chainId}-${asset.address}`}>
          {asset.symbol}: {asset.balanceFormatted} on chain {asset.chainId}
        </li>
      ))}
    </ul>
  );
}
```

### Config

| Param             | Type       | Default | Description                 |
| ----------------- | ---------- | ------- | --------------------------- |
| `address`         | `string`   |         | Wallet address to query     |
| `supportedChains` | `number[]` |         | Filter to specific chains   |
| `enabled`         | `boolean`  | `true`  | Enable or disable fetching  |
| `refetchInterval` | `number`   |         | Auto refetch interval in ms |

### Return Value

| Field              | Type                   | Description                             |
| ------------------ | ---------------------- | --------------------------------------- |
| `assets`           | `Asset[]`              | Array of deposited assets with balances |
| `loading`          | `boolean`              | True during initial load                |
| `error`            | `string \| null`       | Error message if fetch failed           |
| `hasBalance`       | `boolean`              | Whether user has any balance            |
| `refetch`          | `() => Promise<void>`  | Manually refetch balances               |
| `getAssetsByChain` | `(chainId) => Asset[]` | Filter assets by chain                  |

***

## useWallet

Access wallet connection state and signing actions. Works with both Privy and Dynamic providers.

### Usage

```tsx theme={null}
import { useWallet } from "@spicenet-io/spiceflow-ui";

function WalletInfo() {
  const { address, isConnected, isAuthenticated, provider, actions } = useWallet();

  if (!isConnected) return <p>Not connected</p>;

  return (
    <div>
      <p>Connected via {provider}: {address}</p>
      <button onClick={() => actions.signMessage("Hello")}>Sign Message</button>
    </div>
  );
}
```

### Return Value

| Field                       | Type                                 | Description                 |
| --------------------------- | ------------------------------------ | --------------------------- |
| `isReady`                   | `boolean`                            | Provider is initialized     |
| `isAuthenticated`           | `boolean`                            | User has authenticated      |
| `isConnected`               | `boolean`                            | Wallet is connected         |
| `address`                   | `Address \| undefined`               | Connected wallet address    |
| `provider`                  | `"privy" \| "dynamic" \| null`       | Active provider             |
| `actions.signMessage`       | `(message) => Promise<{signature}>`  | Sign a message              |
| `actions.signAuthorization` | `(params) => Promise<Authorization>` | Sign EIP 7702 authorization |

***

## useEmbeddedWalletAddress

Get the Privy embedded wallet address. Returns `undefined` if no embedded wallet exists or in non 7702 mode.

### Usage

```tsx theme={null}
import { useEmbeddedWalletAddress } from "@spicenet-io/spiceflow-ui";

function EmbeddedWallet() {
  const embeddedAddress = useEmbeddedWalletAddress();

  if (!embeddedAddress) return <p>No embedded wallet</p>;
  return <p>Embedded: {embeddedAddress}</p>;
}
```

***

## useAssetInput

Manage asset selection and amount input state. Used to control the asset selector in deposit and lock flows from your own UI.

### Usage

```tsx theme={null}
import { useAssetInput } from "@spicenet-io/spiceflow-ui";

function CustomInput() {
  const { selectedAsset, setSelectedAsset, assetAmount, setAssetAmount } = useAssetInput();

  return (
    <input
      type="text"
      value={assetAmount}
      onChange={(e) => setAssetAmount(e.target.value)}
      placeholder="Amount"
    />
  );
}
```

### Return Value

| Field              | Type                    | Description              |
| ------------------ | ----------------------- | ------------------------ |
| `selectedAsset`    | `SelectedAsset \| null` | Currently selected asset |
| `setSelectedAsset` | `(asset) => void`       | Set the selected asset   |
| `assetAmount`      | `string`                | Current amount string    |
| `setAssetAmount`   | `(amount) => void`      | Set the amount           |

***

## useLockDuration

Manage lock duration selection state for the SpiceLockModal.

### Usage

```tsx theme={null}
import { useLockDuration } from "@spicenet-io/spiceflow-ui";

const durationOptions = [
  { label: "1 Month", months: 1 },
  { label: "6 Months", months: 6 },
  { label: "12 Months", months: 12 },
];

function DurationPicker() {
  const { selectedDurationIdx, setSelectedDurationIdx, selectedDuration } = useLockDuration(durationOptions);

  return (
    <div>
      {durationOptions.map((opt, i) => (
        <button key={i} onClick={() => setSelectedDurationIdx(i)}>
          {opt.label} {i === selectedDurationIdx ? "(selected)" : ""}
        </button>
      ))}
    </div>
  );
}
```

***

## useSpicePendingDeposits

Detect funds stranded in the user's embedded wallet (deposits that were sent but not yet credited to Spice balance). Used by SpiceDeposit internally for recovery flows.

### Usage

```tsx theme={null}
import { useSpicePendingDeposits } from "@spicenet-io/spiceflow-ui";

function PendingCheck() {
  const { pendingDeposits } = useSpicePendingDeposits({
    chainIds: [8453, 4114],
  });

  if (pendingDeposits.length > 0) {
    return <p>You have {pendingDeposits.length} pending deposit(s) to recover.</p>;
  }
  return null;
}
```

***

## useSpiceBrand

Resolve the current theme from the provider's `brand` prop and any component level `styles`/`dark` overrides. Only used when building custom components that need to match the SDK's look.

### Usage

```tsx theme={null}
import { useSpiceBrand } from "@spicenet-io/spiceflow-ui";

function CustomCard({ styles, dark }) {
  const { primaryColor, dk, palette } = useSpiceBrand(styles, dark);

  return (
    <div style={{
      backgroundColor: palette.cardBg,
      color: palette.textPrimary,
      border: `1px solid ${palette.cardBorder}`,
    }}>
      Themed card
    </div>
  );
}
```

### Return Value

| Field          | Type                  | Description                           |
| -------------- | --------------------- | ------------------------------------- |
| `dark`         | `boolean`             | Whether dark mode is active           |
| `primaryColor` | `string`              | Brand accent color                    |
| `theme`        | `Theme`               | Full theme object                     |
| `dk`           | `ResolvedDarkPalette` | Dark palette values                   |
| `palette`      | `ResolvedDarkPalette` | Mode resolved palette (light or dark) |

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Components" icon="window" href="/sdk/components">
    Use prebuilt components for common flows
  </Card>

  <Card title="Styling" icon="palette" href="/sdk/styling">
    Customize appearance with the brand system
  </Card>

  <Card title="API Reference" icon="terminal" href="/api-reference">
    Explore the REST API for advanced use cases
  </Card>

  <Card title="Configuration" icon="sliders" href="/sdk/configuration">
    Configure chains and providers
  </Card>
</CardGroup>
