# Best Practices

Follow these best practices for robust error handling in your application.

### Always Use Try-Catch

Wrap SDK calls in try-catch blocks:

```typescript
try {
  const vault = await sdk.vault.getVaultByKey("yusd", 1);
} catch (error) {
  // Handle error
}
```

### Check Error Types

Use `instanceof` to check error types:

```typescript
import {
  AuthenticationError,
  NetworkError,
  ValidationError,
} from "yieldfi-sdk";

try {
  await sdk.auth.login(credentials);
} catch (error) {
  if (error instanceof AuthenticationError) {
    // Handle auth errors
  } else if (error instanceof NetworkError) {
    // Handle network errors
  } else if (error instanceof ValidationError) {
    // Handle validation errors
  }
}
```

### Provide User-Friendly Messages

Translate technical errors to user-friendly messages:

```typescript
function getUserFriendlyError(error: SDKError): string {
  if (error instanceof AuthenticationError) {
    return "Please login again";
  } else if (error instanceof NetworkError) {
    if (error.statusCode === 503) {
      return "Service temporarily unavailable. Please try again later.";
    }
    return "Network error. Please check your connection.";
  } else if (error instanceof ValidationError) {
    return "Please check your input and try again.";
  }
  return "An error occurred. Please try again.";
}
```

### Implement Retry Logic

For network errors, implement retry logic:

```typescript
async function withRetry<T>(
  fn: () => Promise<T>,
  maxRetries = 3
): Promise<T> {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (error instanceof NetworkError && i < maxRetries - 1) {
        await new Promise((resolve) => setTimeout(resolve, 1000 * (i + 1)));
        continue;
      }
      throw error;
    }
  }
  throw new Error("Max retries exceeded");
}

// Usage
const vault = await withRetry(() =>
  sdk.vault.getVaultByKey("yusd", 1)
);
```

### Handle Token Expiration

Always handle token expiration gracefully:

```typescript
async function makeAuthenticatedRequest<T>(
  apiCall: (token: string) => Promise<T>
): Promise<T> {
  let accessToken = localStorage.getItem("accessToken");

  if (!accessToken || isTokenExpired(accessToken)) {
    accessToken = await refreshToken();
    if (!accessToken) {
      throw new AuthenticationError("Please login again");
    }
  }

  try {
    return await apiCall(accessToken);
  } catch (error) {
    if (error instanceof AuthenticationError) {
      // Token invalid, try refresh once
      accessToken = await refreshToken();
      if (accessToken) {
        return await apiCall(accessToken);
      }
    }
    throw error;
  }
}
```

### Log Errors Appropriately

Log errors for debugging but don't expose sensitive information:

```typescript
try {
  await sdk.auth.login(credentials);
} catch (error) {
  // Log full error for debugging (server-side or dev only)
  console.error("Login error:", error);

  // Show user-friendly message
  showError("Login failed. Please try again.");

  // Don't expose:
  // - Token values
  // - Internal error details
  // - Stack traces (to users)
}
```

### Handle Loading States

Show loading states during API calls:

```typescript
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

async function fetchVaults() {
  setLoading(true);
  setError(null);

  try {
    const vaults = await sdk.vault.getVaults({ chainId: 1 });
    return vaults;
  } catch (err: any) {
    setError(err.message);
    throw err;
  } finally {
    setLoading(false);
  }
}
```

### Graceful Degradation

Handle partial failures gracefully:

```typescript
async function loadDashboard() {
  const results = await Promise.allSettled([
    sdk.vault.getProtocolStats(),
    sdk.vault.getVaults({ chainId: 1 }),
    sdk.vault.getStrategies(),
  ]);

  const stats = results[0].status === "fulfilled" ? results[0].value : null;
  const vaults = results[1].status === "fulfilled" ? results[1].value : null;
  const strategies = results[2].status === "fulfilled" ? results[2].value : null;

  // Show available data, indicate missing data
  return { stats, vaults, strategies };
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.yield.fi/earn-with-yieldfi/integration-sdk/error-handling/best-practices.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
