Suilend SDK

A TypeScript SDK for interacting with the Suilend lending protocol on the Sui blockchain. This SDK provides a complete interface for lending, borrowing, liquidity mining, and administrative operations.

Table of Contents

  • [Installation]

  • [Quick Start]

  • [Architecture Overview]

  • [Core Concepts]

  • [API Reference]

  • [Examples]

  • [Generated Code]

  • [Types and Enums]

  • [Contributing]

  • [Support]

Installation

npm install @suilend/sdk

Peer Dependencies

The SDK requires the following peer dependencies:

npm install @mysten/[email protected] @mysten/[email protected] @suilend/sui-fe@^0.3.5

Quick Start

import { SuilendClient, LENDING_MARKET_ID } from "@suilend/sdk";
import { SuiClient } from "@mysten/sui/client";
import { Transaction } from "@mysten/sui/transactions";

// Initialize Sui client
const suiClient = new SuiClient({ url: "https://fullnode.mainnet.sui.io" });

// Initialize Suilend client
const suilendClient = await SuilendClient.initialize(
  LENDING_MARKET_ID,
  suiClient
);

// Create a transaction
const transaction = new Transaction();

// Deposit tokens into the lending market
await suilendClient.depositIntoObligation(
  userAddress,
  "0x2::sui::SUI", // SUI token type
  "1000000000", // 1 SUI (in MIST)
  transaction,
  obligationOwnerCapId
);

// Execute the transaction
const result = await suiClient.signAndExecuteTransaction({
  signer: keypair,
  transaction,
});

Architecture Overview

The Suilend SDK is organized into several core modules:

Core Modules

  • Client (SuilendClient): Main interface for all lending operations

  • API: Event fetching and blockchain data retrieval

  • Parsers: Data structure parsing and validation utilities

  • Swap: DEX integration for token swapping operations

  • Utils: General utilities and helper functions

  • Generated: Auto-generated code from on-chain smart contracts

Key Components

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│ SuilendClient   │────│ Lending Market  │────│     Reserves    │
└─────────────────┘    └─────────────────┘    └─────────────────┘
        │                      │                        │
        │              ┌─────────────────┐              │
        └──────────────│ Obligations     │──────────────┘
                       └─────────────────┘

Core Concepts

Lending Markets

Lending markets are the primary containers for reserves and obligations. Each market has:

  • A unique market ID

  • A specific coin type (collateral type)

  • Multiple reserves for different assets

  • Associated obligations for users

Reserves

Reserves represent individual asset pools within a lending market:

  • Store deposited liquidity

  • Track borrowing activity

  • Manage interest rates and rewards

  • Issue cTokens (claim tokens) to depositors

Obligations

Obligations represent user positions within a lending market:

  • Track deposited collateral (cTokens)

  • Track borrowed amounts

  • Calculate health ratios

  • Manage liquidation risk

cTokens (Claim Tokens)

cTokens represent ownership of deposited assets:

  • Earned when depositing into reserves

  • Accrue value over time through interest

  • Can be redeemed for underlying assets

  • Used as collateral for borrowing

API Reference

SuilendClient

The main client class for interacting with Suilend protocol.

Initialization

class SuilendClient {
  static async initialize(
    lendingMarketId: string,
    lendingMarketType: string,
    client: SuiClient,
    logPackageId?: boolean
  ): Promise<SuilendClient>;
}

Core Operations

Deposit Operations

// Deposit tokens and receive cTokens
async depositLiquidityAndGetCTokens(
  ownerId: string,
  coinType: string,
  value: string,
  transaction: Transaction
): Promise<TransactionResult>

// Deposit into an obligation as collateral
async depositIntoObligation(
  ownerId: string,
  coinType: string,
  value: string,
  transaction: Transaction,
  obligationOwnerCapId: string | TransactionResult
): Promise<void>

Withdrawal Operations

// Withdraw collateral from obligation
async withdraw(
  obligationOwnerCapId: string,
  obligationId: string,
  coinType: string,
  value: string,
  transaction: Transaction
): Promise<TransactionResult>

// Redeem cTokens for underlying assets
redeem(
  ctokens: TransactionObjectInput,
  coinType: string,
  exemption: TransactionObjectInput,
  transaction: Transaction
): TransactionResult

Borrowing Operations

// Borrow against collateral
async borrow(
  obligationOwnerCapId: string,
  obligationId: string,
  coinType: string,
  value: string,
  transaction: Transaction
): Promise<TransactionResult>

// Repay borrowed amount
async repayIntoObligation(
  ownerId: string,
  obligationId: string,
  coinType: string,
  value: string,
  transaction: Transaction
): Promise<void>

Liquidation Operations

// Liquidate unhealthy obligation
async liquidate(
  transaction: Transaction,
  obligation: Obligation<string>,
  repayCoinType: string,
  withdrawCoinType: string,
  repayCoinId: TransactionObjectInput
): Promise<TransactionResult>

Reward Operations

// Claim rewards from liquidity mining
claimRewards(
  ownerId: string,
  obligationOwnerCapId: string,
  rewards: ClaimRewardsReward[],
  transaction: Transaction
): {
  transaction: Transaction;
  mergedCoinsMap: Record<string, TransactionObjectArgument>;
}

// Add reward to a reserve
async addReward(
  ownerId: string,
  lendingMarketOwnerCapId: string,
  reserveArrayIndex: bigint,
  isDepositReward: boolean,
  rewardCoinType: string,
  rewardValue: string,
  startTimeMs: bigint,
  endTimeMs: bigint,
  transaction: Transaction,
  mergeCoins?: boolean
): Promise<void>

Administrative Operations

// Create new reserve
async createReserve(
  lendingMarketOwnerCapId: string,
  transaction: Transaction,
  pythPriceId: string,
  coinType: string,
  createReserveConfigArgs: CreateReserveConfigArgs
): Promise<void>

// Update reserve configuration
updateReserveConfig(
  lendingMarketOwnerCapId: string,
  transaction: Transaction,
  coinType: string,
  createReserveConfigArgs: CreateReserveConfigArgs
): void

Data Retrieval

// Get obligation data
static async getObligation(
  obligationId: string,
  lendingMarketTypeArgs: string[],
  client: SuiClient
): Promise<Obligation<string>>

// Get obligation owner capabilities
static async getObligationOwnerCaps(
  ownerId: string,
  lendingMarketTypeArgs: string[],
  client: SuiClient
): Promise<ObligationOwnerCap<string>[]>

Events API

The SDK provides comprehensive event parsing for tracking protocol activity:

// Event types available
type ApiReserveAssetDataEvent = {
  id: number;
  lendingMarketId: string;
  coinType: string;
  reserveId: string;
  availableAmount: string;
  supplyAmount: string;
  borrowedAmount: string;
  // ... additional fields
};

type ApiDepositEvent = {
  id: number;
  lendingMarketId: string;
  coinType: string;
  obligationId: string;
  ctokenAmount: string;
  // ... additional fields
};

// Similar events for withdraw, borrow, repay, liquidate, etc.

Swap Integration

The SDK includes DEX aggregation capabilities:

// Get swap quote
async function getQuote(
  fromToken: string,
  toToken: string,
  amount: string,
  slippage: number
): Promise<SwapQuote>;

// Execute swap transaction
async function executeSwap(
  quote: SwapQuote,
  transaction: Transaction
): Promise<void>;

Examples

Complete Lending Flow

import { SuilendClient, LENDING_MARKET_ID, Side } from "@suilend/sdk";
import { SuiClient } from "@mysten/sui/client";
import { Transaction } from "@mysten/sui/transactions";
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";

async function lendingExample() {
  // Initialize clients
  const suiClient = new SuiClient({ url: "https://fullnode.mainnet.sui.io" });
  const suilendClient = await SuilendClient.initialize(
    LENDING_MARKET_ID,
    suiClient
  );

  const keypair = Ed25519Keypair.generate();
  const userAddress = keypair.toSuiAddress();

  // 1. Create obligation
  const createObligationTx = new Transaction();
  const obligationOwnerCap = suilendClient.createObligation(createObligationTx);

  await suiClient.signAndExecuteTransaction({
    signer: keypair,
    transaction: createObligationTx,
  });

  // 2. Deposit SUI as collateral
  const depositTx = new Transaction();
  await suilendClient.depositIntoObligation(
    userAddress,
    "0x2::sui::SUI",
    "5000000000", // 5 SUI
    depositTx,
    obligationOwnerCap
  );

  await suiClient.signAndExecuteTransaction({
    signer: keypair,
    transaction: depositTx,
  });

  // 3. Borrow USDC
  const borrowTx = new Transaction();
  const obligationId = "your-obligation-id";

  await suilendClient.borrow(
    obligationOwnerCap,
    obligationId,
    "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN", // USDC
    "1000000", // 1 USDC
    borrowTx
  );

  await suiClient.signAndExecuteTransaction({
    signer: keypair,
    transaction: borrowTx,
  });

  // 4. Claim rewards
  const rewardsTx = new Transaction();
  const rewards = [
    {
      reserveArrayIndex: 0n,
      rewardIndex: 0n,
      rewardCoinType: "0x2::sui::SUI",
      side: Side.DEPOSIT,
    },
  ];

  suilendClient.claimRewards(
    userAddress,
    obligationOwnerCap,
    rewards,
    rewardsTx
  );

  await suiClient.signAndExecuteTransaction({
    signer: keypair,
    transaction: rewardsTx,
  });
}

Administrative Example

async function adminExample() {
  const suiClient = new SuiClient({ url: "https://fullnode.mainnet.sui.io" });
  const suilendClient = await SuilendClient.initialize(
    LENDING_MARKET_ID,
    suiClient
  );

  const adminKeypair = Ed25519Keypair.fromSecretKey(/* admin secret key */);
  const lendingMarketOwnerCapId = "owner-cap-id";

  // Create new reserve
  const createReserveTx = new Transaction();

  await suilendClient.createReserve(
    lendingMarketOwnerCapId,
    createReserveTx,
    "pyth-price-feed-id",
    "0x2::sui::SUI",
    {
      // Reserve configuration parameters
      openLtvPct: 70,
      closeLtvPct: 75,
      maxCloseLtvPct: 80,
      borrowWeightBps: 11000,
      depositLimitUsd: 10000000,
      borrowLimitUsd: 5000000,
      // ... additional config
    }
  );

  await suiClient.signAndExecuteTransaction({
    signer: adminKeypair,
    transaction: createReserveTx,
  });

  // Add liquidity mining rewards
  const addRewardTx = new Transaction();

  await suilendClient.addReward(
    adminKeypair.toSuiAddress(),
    lendingMarketOwnerCapId,
    0n, // reserve array index
    true, // is deposit reward
    "0x2::sui::SUI",
    "1000000000000", // 1000 SUI in rewards
    BigInt(Date.now()), // start time
    BigInt(Date.now() + 30 * 24 * 60 * 60 * 1000), // end time (30 days)
    addRewardTx
  );

  await suiClient.signAndExecuteTransaction({
    signer: adminKeypair,
    transaction: addRewardTx,
  });
}

Generated Code

The SDK includes auto-generated TypeScript bindings for all on-chain smart contract functions and data structures. These are located in the _generated directory and provide:

  • Function bindings: Direct access to all smart contract functions

  • Struct definitions: TypeScript interfaces for all on-chain data structures

  • Type safety: Full type checking for all blockchain interactions

The generated code is organized by package and module:

  • suilend/: Core Suilend protocol functions and structs

  • _dependencies/: External dependencies (Sui framework, Pyth, etc.)

  • _framework/: Framework utilities and loaders

Types and Enums

Core Enums

enum Side {
  DEPOSIT = "deposit",
  BORROW = "borrow",
}

enum Action {
  DEPOSIT = "deposit",
  WITHDRAW = "withdraw",
  BORROW = "borrow",
  REPAY = "repay",
}

Key Interfaces

interface ClaimRewardsReward {
  reserveArrayIndex: bigint;
  rewardIndex: bigint;
  rewardCoinType: string;
  side: Side;
}

interface CreateReserveConfigArgs {
  openLtvPct: number;
  closeLtvPct: number;
  maxCloseLtvPct: number;
  borrowWeightBps: number;
  depositLimitUsd: number;
  borrowLimitUsd: number;
  // ... additional configuration fields
}

Configuration

Environment Variables

The SDK behavior can be configured using environment variables:

  • NEXT_PUBLIC_SUILEND_USE_BETA_MARKET: Set to "true" to use beta market endpoints

Constants

// Available lending markets
export const LENDING_MARKETS: UiLendingMarket[];
export const LENDING_MARKET_ID: string; // Main market ID
export const LENDING_MARKET_TYPE: string; // Main market type

// Precision constants
export const WAD = new BigNumber(10).pow(18);

Error Handling

The SDK uses standard JavaScript Error objects and blockchain-specific errors from the Sui SDK. Always wrap SDK calls in try-catch blocks:

try {
  await suilendClient.depositIntoObligation(/* ... */);
} catch (error) {
  console.error("Deposit failed:", error.message);
  // Handle error appropriately
}

Performance Considerations

  • Batch operations: Use transactions to batch multiple operations

  • Refresh cycles: Call refreshAll() to update obligation state before operations

  • Gas optimization: Merge coins when possible to reduce transaction complexity

Contributing

  1. Fork the repository

  2. Create a feature branch

  3. Make your changes

  4. Add tests if applicable

  5. Submit a pull request

Support

  • Documentation: This README and inline code documentation

  • Discord: Join our #dev-support channel

  • Issues: Report bugs on GitHub Issues

License

MIT License - see LICENSE file for details.