Fixed-Rate Lending SDK

Documentation for the Fixed-Rate Lending SDK

The Fixed-Rate Lending SDK is a comprehensive toolkit for developers to integrate and interact with the Secured Finance Fixed-Rate Lending protocol.

Overview

The Fixed-Rate Lending protocol provides a platform for fixed-rate lending and borrowing through an order book system. The SDK provides a programmatic interface to interact with the protocol, allowing developers to build applications that leverage Fixed-Rate Lending functionality.

How It Works

The Fixed-Rate Lending SDK is built on top of viem and provides a type-safe interface to interact with the Fixed-Rate Lending smart contracts. It abstracts away the complexity of direct contract interactions and provides a more developer-friendly API.

Installation

The Fixed-Rate Lending SDK packages are hosted on GitHub Packages registry, not the public NPM registry. You'll need to configure your .npmrc file to access them:

# Add this to your .npmrc file
@secured-finance:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN

# Then install the individual packages
npm install @secured-finance/sf-client
npm install @secured-finance/sf-graph-client
npm install @secured-finance/sf-core

For more details on setting up authentication for GitHub Packages, see the GitHub documentation.

Key Components

The Fixed-Rate Lending SDK consists of several packages:

sf-client

The core package for interacting with the Fixed-Rate Lending protocol.

import { SecuredFinanceClient } from "@secured-finance/sf-client";

sf-graph-client

Utilities for querying the Fixed-Rate Lending subgraph.

import { GraphClient } from "@secured-finance/sf-graph-client";

sf-core

Core components used across different Secured Finance projects.

import { Currency, Token } from "@secured-finance/sf-core";

Basic Usage

Connecting to the Protocol

import { SecuredFinanceClient } from "@secured-finance/sf-client";
import { createPublicClient, createWalletClient, http } from "viem";
import { filecoin } from "viem/chains";

// Connect to the protocol
async function connectToProtocol() {
  // Create viem clients
  const publicClient = createPublicClient({
    chain: filecoin,
    transport: http()
  });
  
  const walletClient = createWalletClient({
    chain: filecoin,
    transport: http()
  });
  
  // Create the Secured Finance client
  const client = new SecuredFinanceClient();
  await client.init(publicClient, walletClient);
  
  return client;
}

Reading Protocol State

import { Currency } from "@secured-finance/sf-core";

// Get supported currencies
async function getSupportedCurrencies(client) {
  const currencies = await client.getCurrencies();
  console.log("Supported currencies:", currencies);
  return currencies;
}

// Get lending markets
async function getLendingMarkets(client, currency) {
  const maturities = await client.getMaturities(currency);
  console.log("Available maturities:", maturities);
  
  const orderBookDetails = await client.getOrderBookDetailsPerCurrency(currency);
  console.log("Order book details:", orderBookDetails);
  
  return { maturities, orderBookDetails };
}

// Get order book
async function getOrderBook(client, currency, maturity) {
  const orderBookDetail = await client.getOrderBookDetail(currency, maturity);
  console.log("Order book detail:", orderBookDetail);
  
  const lendOrders = await client.getLendOrderBook(currency, maturity, 0, 10);
  console.log("Lend orders:", lendOrders);
  
  const borrowOrders = await client.getBorrowOrderBook(currency, maturity, 0, 10);
  console.log("Borrow orders:", borrowOrders);
  
  return { orderBookDetail, lendOrders, borrowOrders };
}

// Get user positions
async function getUserPositions(client, account) {
  const positions = await client.getPositions(account);
  console.log("User positions:", positions);
  return positions;
}

Order Operations

import { Currency } from "@secured-finance/sf-core";
import { OrderSide, WalletSource } from "@secured-finance/sf-client";

// Place a lend order
async function placeLendOrder(client, currency, maturity, amount, unitPrice) {
  const tx = await client.placeOrder(
    currency,
    maturity,
    OrderSide.LEND,
    amount,
    WalletSource.METAMASK,
    unitPrice
  );
  
  console.log("Lend order placed:", tx);
  return tx;
}

// Place a borrow order
async function placeBorrowOrder(client, currency, maturity, amount, unitPrice) {
  const tx = await client.placeOrder(
    currency,
    maturity,
    OrderSide.BORROW,
    amount,
    WalletSource.METAMASK,
    unitPrice
  );
  
  console.log("Borrow order placed:", tx);
  return tx;
}

// Cancel an order
async function cancelOrder(client, currency, maturity, orderId) {
  const tx = await client.cancelLendingOrder(currency, maturity, orderId);
  console.log("Order cancelled:", tx);
  return tx;
}

Collateral Management

// Deposit collateral
async function depositCollateral(client, currency, amount) {
  const tx = await client.depositCollateral(currency, amount);
  console.log("Collateral deposited:", tx);
  return tx;
}

// Get protocol deposit amount
async function getProtocolDepositAmount(client) {
  const depositAmount = await client.getProtocolDepositAmount();
  console.log("Protocol deposit amount:", depositAmount);
  return depositAmount;
}

Position Management

// Unwind a position
async function unwindPosition(client, currency, maturity) {
  const tx = await client.unwindPosition(currency, maturity);
  console.log("Position unwound:", tx);
  return tx;
}

// Get total present value
async function getTotalPresentValue(client) {
  const presentValue = await client.getTotalPresentValueInBaseCurrency();
  console.log("Total present value:", presentValue);
  return presentValue;
}

Advanced Usage

Using the Graph Client

import { GraphClient, useQuery } from "@secured-finance/sf-graph-client";
import { useEffect, useState } from "react";

// Create a graph client for a specific network
const graphClient = new GraphClient({
  uri: "https://api.studio.thegraph.com/query/64582/sf-prd-arbitrum-sepolia/version/latest"
});

// Example 1: Simple query using the GraphClient directly
async function queryLendingMarkets() {
  try {
    // Define the query document
    const { lendingMarkets } = await graphClient.query({
      lendingMarkets: {
        id: true,
        currency: {
          id: true,
          symbol: true,
          decimals: true
        },
        maturity: true,
        isReady: true
      }
    });
    
    console.log("Lending markets:", lendingMarkets);
    return lendingMarkets;
  } catch (error) {
    console.error("Error querying lending markets:", error);
    return [];
  }
}

// Example 2: Using the useQuery hook in a React component
function LendingMarketsComponent() {
  // Define the query document
  const queryDocument = {
    lendingMarkets: {
      id: true,
      currency: {
        id: true,
        symbol: true
      },
      maturity: true,
      isReady: true
    }
  };
  
  // Execute the query
  const { data, loading, error } = useQuery(queryDocument, {
    client: graphClient,
    variables: {},
    fetchPolicy: "network-only"
  });
  
  // Handle loading and error states
  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  
  // Render the data
  return (
    <div>
      <h2>Available Lending Markets</h2>
      <ul>
        {data?.lendingMarkets?.map(market => (
          <li key={market.id}>
            {market.currency.symbol} - Maturity: {new Date(Number(market.maturity) * 1000).toLocaleDateString()}
          </li>
        ))}
      </ul>
    </div>
  );
}

Price Calculations

import { getUTCMonthYear } from "@secured-finance/sf-core";

// Convert unit price to APR
function unitPriceToAPR(unitPrice, maturity) {
  const now = Math.floor(Date.now() / 1000);
  const secondsToMaturity = maturity - now;
  const secondsPerYear = 365 * 24 * 60 * 60; // 31,536,000
  const yearsToMaturity = secondsToMaturity / secondsPerYear;
  
  // Different calculation methods based on maturity
  if (yearsToMaturity < 1) {
    // For bonds with maturity less than 1 year (linear calculation)
    return ((10000 / unitPrice) - 1) * (secondsPerYear / secondsToMaturity) * 100;
  } else {
    // For bonds with maturity greater than 1 year (annual compounding)
    return (Math.pow(10000 / unitPrice, 1 / yearsToMaturity) - 1) * 100;
  }
}

// Format maturity date
function formatMaturity(maturity) {
  return getUTCMonthYear(maturity, true);
}

// Calculate order estimation
async function calculateOrderEstimation(client, currency, maturity, account, side, amount, unitPrice) {
  const estimation = await client.getOrderEstimation(
    currency,
    maturity,
    account,
    side,
    amount,
    unitPrice
  );
  
  console.log("Order estimation:", estimation);
  return estimation;
}

FAQ

How do I handle transaction errors?

The SDK throws descriptive error objects that contain information about the failure. Wrap your transactions in try-catch blocks to handle errors gracefully.

try {
  await client.placeOrder(
    currency,
    maturity,
    OrderSide.LEND,
    amount,
    WalletSource.METAMASK,
    unitPrice
  );
} catch (error) {
  if (error.message.includes("InsufficientDepositAmount")) {
    console.error("Insufficient deposit amount. Deposit more collateral.");
  } else {
    console.error("Transaction failed:", error);
  }
}

How do I convert between unit price and APR?

The conversion between Zero-Coupon Bond prices and APR varies depending on the maturity period. For detailed information, refer to the official documentation on ZC Bond Price to APR conversion.

The calculation is implemented in the Price Calculations section above.

What networks does the SDK support?

The SDK supports all networks where the Fixed-Rate Lending protocol is deployed, including Ethereum, Arbitrum, and Filecoin.

Last updated

Was this helpful?