Skip to main content

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.

This example demonstrates how to combine the Amplify SDK with the Privy React SDK to prepare approvals, submit deposits, and display transaction status inside a React app.

Overview

  • Access the embedded or external wallet provided by Privy.
  • Prepare approval and deposit calldata with the Amplify helpers.
  • Submit both transactions with sendTransaction.
  • Track optimistic UI state and surface errors.

Prerequisites

  • React 18+
  • @privy-io/react-auth >= 3
  • @paxoslabs/amplify-sdk (initialized via initAmplifySDK)
  • viem >= 2.0.0 for calldata encoding and allowance checks
  • Privy provider configured at the app root (<PrivyProvider appId="...">)

Deposit Hook

import { useCallback, useMemo, useState } from "react";
import { encodeFunctionData } from "viem";
import {
  isDepositSpendApproved,
  prepareApproveDepositTokenTxData,
  prepareDepositTxData,
  type YieldType,
} from "@paxoslabs/amplify-sdk";
import { usePrivy, useWallets } from "@privy-io/react-auth";

interface DepositParams {
  yieldType: YieldType;
  depositToken: `0x${string}`;
  recipientAddress: `0x${string}`;
  depositAmount: string;
  chainId: number;
  slippage?: number;
}

export function usePrivyDeposit() {
  const { sendTransaction } = usePrivy();
  const { wallets } = useWallets();
  const wallet = useMemo(() => wallets.find(Boolean), [wallets]);

  const [txHash, setTxHash] = useState<`0x${string}` | null>(null);
  const [status, setStatus] = useState<
    "idle" | "checking" | "approving" | "depositing" | "success"
  >("idle");
  const [error, setError] = useState<Error | null>(null);

  const run = useCallback(
    async ({
      yieldType,
      depositToken,
      recipientAddress,
      depositAmount,
      chainId,
      slippage = 100,
    }: DepositParams) => {
      if (!wallet) {
        throw new Error("Connect a Privy wallet before depositing.");
      }

      setStatus("checking");
      setError(null);
      setTxHash(null);

      try {
        const approved = await isDepositSpendApproved({
          yieldType,
          depositToken,
          recipientAddress,
          chainId,
        });

        if (!approved) {
          setStatus("approving");
          const approval = await prepareApproveDepositTokenTxData({
            yieldType,
            depositToken,
            depositAmount,
            chainId,
          });

          await sendTransaction({
            chainId: approval.chainId,
            to: approval.address,
            data: encodeFunctionData({
              abi: approval.abi,
              functionName: approval.functionName,
              args: approval.args,
            }),
          });
        }

        setStatus("depositing");
        const deposit = await prepareDepositTxData({
          yieldType,
          recipientAddress,
          depositToken,
          depositAmount,
          chainId,
          slippage,
        });

        const hash = await sendTransaction({
          chainId: deposit.chainId,
          to: deposit.address,
          data: encodeFunctionData({
            abi: deposit.abi,
            functionName: deposit.functionName,
            args: deposit.args,
          }),
        });

        setTxHash(hash as `0x${string}`);
        setStatus("success");
      } catch (err) {
        const message = err instanceof Error ? err : new Error(String(err));
        setError(message);
        setStatus("idle");
        throw err;
      }
    },
    [wallet, sendTransaction]
  );

  return { run, status, error, txHash };
}

Component Usage

import { usePrivyDeposit } from "./usePrivyDeposit";
import { useWallets } from "@privy-io/react-auth";
import { useMemo } from "react";
import { YieldType } from "@paxoslabs/amplify-sdk";

const CORE_DEPOSIT_TOKEN = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; // USDC

export function PrivyDepositButton() {
  const { wallets } = useWallets();
  const wallet = useMemo(() => wallets.find(Boolean), [wallets]);
  const { run, status, txHash, error } = usePrivyDeposit();

  if (!wallet) {
    return <p>Connect with Privy to deposit.</p>;
  }

  async function handleClick() {
    await run({
      yieldType: YieldType.CORE,
      depositToken: CORE_DEPOSIT_TOKEN,
      recipientAddress: wallet.address as `0x${string}`,
      depositAmount: "100",
      chainId: 1,
    });
  }

  return (
    <section>
      <button
        onClick={handleClick}
        disabled={status !== "idle" && status !== "success"}
      >
        {status === "checking" && "Checking allowance…"}
        {status === "approving" && "Approving…"}
        {status === "depositing" && "Depositing…"}
        {status === "success" && "Deposit Again"}
        {(status === "idle" || status === "success") && "Deposit with Privy"}
      </button>

      {txHash && (
        <p>
          Deposit sent:{" "}
          <a
            href={`https://etherscan.io/tx/${txHash}`}
            target="_blank"
            rel="noreferrer"
          >
            {txHash}
          </a>
        </p>
      )}

      {error && <p role="alert">Deposit failed: {error.message}</p>}
    </section>
  );
}
sendTransaction resolves with the transaction hash. Add receipt polling, analytics, and user notifications to fit your UX requirements.