> ## Documentation Index
> Fetch the complete documentation index at: https://developers.paxoslabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Privy Deposit

> Complete deposit flow using Privy embedded wallets with unified API

This example demonstrates a complete deposit flow using Privy for wallet management and the unified deposit API.

<Callout type="info">
  This example uses the unified deposit API which automatically detects the optimal authorization method (permit vs approval).
</Callout>

## Prerequisites

* Node.js 18+
* Privy App ID from [Privy Dashboard](https://dashboard.privy.io)
* Amplify API key from Paxos Labs

## Installation

```bash theme={null}
pnpm add @paxoslabs/amplify-sdk @privy-io/react-auth viem @tanstack/react-query
```

## Complete Example

### useDeposit Hook

```tsx theme={null}
// src/hooks/useDeposit.ts
import { useState, useCallback } from "react";
import { encodeFunctionData } from "viem";
import { mainnet } from "viem/chains";
import { usePrivy, useWallets } from "@privy-io/react-auth";
import {
  prepareDepositAuthorization,
  prepareDepositTxData,
  prepareDepositWithPermitTxData,
  DepositAuthMethod,
  YieldType,
} from "@paxoslabs/amplify-sdk";

interface DepositParams {
  amount: string;
  depositToken: `0x${string}`;
  yieldType: YieldType;
}

export function useDeposit() {
  const { sendTransaction } = usePrivy();
  const { wallets } = useWallets();
  const [status, setStatus] = useState<string>("");
  const [isLoading, setIsLoading] = useState(false);

  const deposit = useCallback(
    async ({ amount, depositToken, yieldType }: DepositParams) => {
      const wallet = wallets[0];
      if (!wallet) {
        throw new Error("Connect a wallet first");
      }

      setIsLoading(true);
      const owner = wallet.address as `0x${string}`;

      try {
        const params = {
          yieldType,
          depositToken,
          depositAmount: amount,
          recipientAddress: owner,
          chainId: mainnet.id,
        };

        // Step 1: Get authorization method
        setStatus("Checking authorization...");
        const auth = await prepareDepositAuthorization(params);

        // Step 2: Handle based on method
        switch (auth.method) {
          case DepositAuthMethod.PERMIT: {
            setStatus("Please sign permit in your wallet...");
            const provider = await wallet.getEthereumProvider();
            const signature = (await provider.request({
              method: "eth_signTypedData_v4",
              params: [
                owner,
                JSON.stringify({
                  domain: auth.permitData.domain,
                  types: auth.permitData.types,
                  primaryType: auth.permitData.primaryType,
                  message: auth.permitData.message,
                }),
              ],
            })) as `0x${string}`;

            setStatus("Submitting deposit...");
            const permitTx = await prepareDepositWithPermitTxData({
              ...params,
              signature,
              deadline: BigInt(auth.permitData.message.deadline),
            });

            const { abi: permitAbi, functionName: permitFn, args: permitArgs } = permitTx.data;
            await sendTransaction({
              chainId: permitTx.chainId,
              to: permitTx.address,
              data: encodeFunctionData({
                abi: permitAbi,
                functionName: permitFn,
                args: permitArgs,
              }),
            });
            break;
          }

          case DepositAuthMethod.APPROVAL: {
            setStatus("Approving token spend...");
            const { abi: approvalAbi, functionName: approvalFn, args: approvalArgs } = auth.txData;
            await sendTransaction({
              chainId: mainnet.id,
              to: auth.txData.address,
              data: encodeFunctionData({
                abi: approvalAbi,
                functionName: approvalFn,
                args: approvalArgs,
              }),
            });

            setStatus("Submitting deposit...");
            const depositTx = await prepareDepositTxData(params);
            const { abi: depositAbi, functionName: depositFn, args: depositArgs } = depositTx;
            await sendTransaction({
              chainId: depositTx.chainId,
              to: depositTx.address,
              data: encodeFunctionData({
                abi: depositAbi,
                functionName: depositFn,
                args: depositArgs,
              }),
            });
            break;
          }

          case DepositAuthMethod.ALREADY_APPROVED: {
            setStatus("Submitting deposit...");
            const directTx = await prepareDepositTxData(params);
            const { abi, functionName, args } = directTx;
            await sendTransaction({
              chainId: directTx.chainId,
              to: directTx.address,
              data: encodeFunctionData({ abi, functionName, args }),
            });
            break;
          }
        }

        setStatus("Deposit successful!");
      } catch (error) {
        setStatus(`Error: ${error instanceof Error ? error.message : "Unknown"}`);
        throw error;
      } finally {
        setIsLoading(false);
      }
    },
    [wallets, sendTransaction]
  );

  return { deposit, status, isLoading };
}
```

### Deposit Component

```tsx theme={null}
// src/components/DepositForm.tsx
import { useState } from "react";
import { YieldType } from "@paxoslabs/amplify-sdk";
import { useDeposit } from "../hooks/useDeposit";

const USDC_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as const;

export function DepositForm() {
  const [amount, setAmount] = useState("100");
  const { deposit, status, isLoading } = useDeposit();

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    await deposit({
      amount,
      depositToken: USDC_ADDRESS,
      yieldType: YieldType.PRIME,
    });
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Amount (USDC):
        <input
          type="number"
          value={amount}
          onChange={(e) => setAmount(e.target.value)}
          disabled={isLoading}
          min="0"
          step="0.01"
        />
      </label>
      <button type="submit" disabled={isLoading}>
        {isLoading ? "Processing..." : "Deposit"}
      </button>
      {status && <p>{status}</p>}
    </form>
  );
}
```

## What This Code Does

1. **Checks authorization method** - Determines if permit, approval, or already approved
2. **Handles permit flow** - Signs typed data off-chain for gas-efficient authorization
3. **Handles approval flow** - Sends approval transaction then deposit
4. **Handles pre-approved** - Deposits directly if allowance exists
5. **Reports status** - Updates UI with current operation status

## Key Features

* **Automatic method detection** - SDK chooses optimal authorization path
* **Type-safe results** - TypeScript discriminated unions for each case
* **Status updates** - Real-time feedback during multi-step flows
* **Error handling** - Catches and reports errors with context

## Troubleshooting

| Issue                    | Solution                                               |
| ------------------------ | ------------------------------------------------------ |
| "SDK not initialized"    | Call `initAmplifySDK()` before using hooks             |
| "Connect a wallet first" | Ensure user is authenticated with Privy                |
| Permit signature fails   | Token may not support EIP-2612, falls back to approval |

For more details, see [Deposits](../functions/deposits).
