Authentication Flow

This example demonstrates a complete authentication flow with token management and error handling.

React Component Example

import { useState, useEffect } from "react";
import { YieldFiSDK, AuthenticationError, NetworkError } from "yieldfi-sdk";
import { ethers } from "ethers";

function AuthExample() {
  const [sdk, setSdk] = useState<YieldFiSDK | null>(null);
  const [user, setUser] = useState<any>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    initializeSDK();
    checkExistingAuth();
  }, []);

  const initializeSDK = async () => {
    try {
      const sdkInstance = await YieldFiSDK.create({
        gatewayUrl: "https://gw.yield.fi",
      });
      setSdk(sdkInstance);
    } catch (err: any) {
      setError(`Failed to initialize SDK: ${err.message}`);
    }
  };

  const checkExistingAuth = async () => {
    const accessToken = localStorage.getItem("accessToken");
    if (!accessToken || !sdk) return;

    try {
      // Verify token is still valid by making a test request
      const transactions = await sdk.vault.getTransactions(
        { chainId: 1, page: 1, pageSize: 1 },
        accessToken
      );

      // Token is valid, load user info
      const userStr = localStorage.getItem("user");
      if (userStr) {
        setUser(JSON.parse(userStr));
      }
    } catch (err) {
      // Token expired or invalid, clear storage
      localStorage.removeItem("accessToken");
      localStorage.removeItem("refreshToken");
      localStorage.removeItem("user");
    }
  };

  const handleLogin = async () => {
    if (!sdk) {
      setError("SDK not initialized");
      return;
    }

    try {
      setLoading(true);
      setError(null);

      // 1. Connect to wallet
      if (!window.ethereum) {
        throw new Error("MetaMask not installed");
      }

      const provider = new ethers.BrowserProvider(window.ethereum);
      await provider.send("eth_requestAccounts", []);
      const signer = await provider.getSigner();
      const address = await signer.getAddress();

      // 2. Generate nonce
      const nonce = await sdk.auth.generateNonce({ address });

      // 3. Sign message
      const signature = await signer.signMessage(nonce.message);

      // 4. Login
      const authResponse = await sdk.auth.login({
        address,
        signature,
        message: nonce.message,
      });

      // 5. Store tokens and user info
      localStorage.setItem("accessToken", authResponse.accessToken);
      localStorage.setItem("refreshToken", authResponse.refreshToken);
      localStorage.setItem("user", JSON.stringify(authResponse.user));

      setUser(authResponse.user);
      console.log("Login successful!");
    } catch (err: any) {
      if (err instanceof AuthenticationError) {
        setError(`Authentication failed: ${err.message}`);
      } else if (err instanceof NetworkError) {
        setError(`Network error: ${err.message}`);
      } else {
        setError(`Login failed: ${err.message}`);
      }
    } finally {
      setLoading(false);
    }
  };

  const handleLogout = async () => {
    if (!sdk) return;

    try {
      const accessToken = localStorage.getItem("accessToken");
      if (accessToken) {
        await sdk.auth.logout(accessToken);
      }
    } catch (err) {
      console.error("Logout error:", err);
    } finally {
      localStorage.removeItem("accessToken");
      localStorage.removeItem("refreshToken");
      localStorage.removeItem("user");
      setUser(null);
    }
  };

  if (!sdk) {
    return <div>Initializing SDK...</div>;
  }

  return (
    <div>
      {user ? (
        <div>
          <p>Logged in as: {user.address}</p>
          <p>Role: {user.role}</p>
          <button onClick={handleLogout}>Logout</button>
        </div>
      ) : (
        <div>
          <button onClick={handleLogin} disabled={loading}>
            {loading ? "Connecting..." : "Connect Wallet"}
          </button>
          {error && <p style={{ color: "red" }}>{error}</p>}
        </div>
      )}
    </div>
  );
}

export default AuthExample;

Token Refresh Utility

Usage in API Calls

Last updated