Skip to main content

Overview

This guide walks you through adding Spice Flow to your app. By the end, your users will be able to deposit assets from any chain into your protocol without bridging. What you’ll build:
  • A wallet connection flow (embedded + external wallet)
  • A deposit interface that accepts any token from any supported chain
  • Cross chain execution powered by EIP 7702

Step 1: Installation

Install the Spice Flow UI SDK and Privy for wallet management:
npm install @spicenet-io/spiceflow-ui @privy-io/react-auth react react-dom viem wagmi @tanstack/react-query axios

Step 2: Setup Provider

Wrap your app with SpiceFlowProvider. This sets up wallet connections, chain configuration, and theming:
"use client"; // For Next.js App Router

import { SpiceFlowProvider } from "@spicenet-io/spiceflow-ui";

function App() {
  return (
    <SpiceFlowProvider
      provider="privy"
      network="mainnet"
      nativeChainId={8453}
      theme={{ primaryColor: "#f97316", dark: true }}
    >
      {/* Your app components go here */}
    </SpiceFlowProvider>
  );
}

export default App;
Get your Privy App ID from privy.io. You can also use Dynamic as your wallet provider. See Configuration for details.

Step 3: Add Deposit Flow

Import SpiceDeposit and provide the on chain calls you want executed on the destination chain:
import { useState } from "react";
import { SpiceFlowProvider, SpiceDeposit } from "@spicenet-io/spiceflow-ui";
import { encodeFunctionData } from "viem";

function App() {
  const [isOpen, setIsOpen] = useState(false);

  // These are the calls that run on the destination chain after the user deposits
  const depositBatches = [
    {
      chainId: 8453, // Base
      calls: [
        { to: TOKEN_ADDRESS, value: 0n, data: encodeApprove(VAULT, amount) },
        { to: VAULT_ADDRESS, value: 0n, data: encodeDeposit(TOKEN_ADDRESS, amount) },
      ],
    },
  ];

  return (
    <SpiceFlowProvider
      provider="privy"
      network="mainnet"
      nativeChainId={8453}
      theme={{ primaryColor: "#f97316", dark: true }}
    >
      <button onClick={() => setIsOpen(true)}>Deposit</button>
      <SpiceDeposit
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        depositBatches={depositBatches}
        styles={{ primaryColor: "#f97316" }}
      />
    </SpiceFlowProvider>
  );
}
That’s it. The SDK handles the entire flow: Privy login, external wallet connection, token selection, escrow deposit, EIP 7702 delegation signing, and solver execution on the destination chain.

Step 4: Add Withdrawals (Optional)

Let users withdraw their Spice balance back to their wallet:
import { SpiceWithdraw } from "@spicenet-io/spiceflow-ui";

<SpiceWithdraw
  isOpen={withdrawOpen}
  onClose={() => setWithdrawOpen(false)}
  styles={{ primaryColor: "#f97316" }}
/>

Complete Example

Here’s a complete Next.js page with deposit and withdraw:
"use client";

import { useState } from "react";
import { SpiceFlowProvider, SpiceDeposit, SpiceWithdraw } from "@spicenet-io/spiceflow-ui";

function DeFiApp() {
  const [depositOpen, setDepositOpen] = useState(false);
  const [withdrawOpen, setWithdrawOpen] = useState(false);

  return (
    <SpiceFlowProvider
      provider="privy"
      network="mainnet"
      nativeChainId={8453}
      theme={{ primaryColor: "#f97316", dark: true }}
    >
      <div style={{ display: "flex", gap: "12px", padding: "40px" }}>
        <button onClick={() => setDepositOpen(true)}>Deposit</button>
        <button onClick={() => setWithdrawOpen(true)}>Withdraw</button>
      </div>

      <SpiceDeposit
        isOpen={depositOpen}
        onClose={() => setDepositOpen(false)}
        depositBatches={[
          {
            chainId: 8453,
            calls: [
              // Your destination chain calls here
            ],
          },
        ]}
        styles={{ primaryColor: "#f97316" }}
        onDepositSuccess={(detail) => {
          console.log("Deposit succeeded:", detail);
        }}
      />

      <SpiceWithdraw
        isOpen={withdrawOpen}
        onClose={() => setWithdrawOpen(false)}
        styles={{ primaryColor: "#f97316" }}
      />
    </SpiceFlowProvider>
  );
}

export default function Home() {
  return <DeFiApp />;
}

Environment Setup

Create a .env.local file in your project root:
NEXT_PUBLIC_PRIVY_APP_ID=your_privy_app_id_here
Get your credentials:
  • Privy: Sign up at privy.io and create an app
  • Dynamic: Sign up at dynamic.xyz and get your environment ID

How It Works

  1. User opens your app and logs in via Privy (creates an embedded wallet)
  2. User connects their external wallet (MetaMask, etc.)
  3. User selects a token and amount to deposit
  4. External wallet sends the token to the embedded wallet, then to the escrow
  5. SDK signs an EIP 7702 delegation and submits it to the solver
  6. Solver executes the depositBatches calls on the destination chain on behalf of the user
  7. Success callback fires
The user never bridges. The user never pays gas on the destination chain.

What’s Next?

Components

Explore all available components and their props

Hooks

Build custom UIs with React hooks

Styling

Customize the appearance to match your brand

Configuration

Configure chains, providers, and execution modes

Using Dynamic Provider

<SpiceFlowProvider
  provider="dynamic"
  dynamicEnvironmentId={process.env.NEXT_PUBLIC_DYNAMIC_ENVIRONMENT_ID}
  network="mainnet"
  nativeChainId={8453}
>
  {children}
</SpiceFlowProvider>

Troubleshooting

”Window is not defined” Error

If you see this in Next.js, ensure you’re using the "use client" directive:
"use client";

import { SpiceFlowProvider } from "@spicenet-io/spiceflow-ui";

Wallet Not Connecting

  1. Check that your provider credentials are correct in .env.local
  2. Ensure you’re using the correct provider name ("privy" or "dynamic")
  3. Check the browser console for any error messages

Need More Help?

Join our Discord

Get help from the community and our team