lulo

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Lulo Development Guide

Lulo 开发指南

A comprehensive guide for integrating Lulo, Solana's only lending aggregator, into your applications. Lulo automatically routes deposits to the highest-yielding DeFi protocols while providing optional smart contract protection.
本指南全面介绍如何将 Solana 唯一的借贷聚合器 Lulo 集成到你的应用中。Lulo 会自动将存款路由至收益最高的 DeFi 协议,同时提供可选的智能合约保护。

What is Lulo?

什么是 Lulo?

Lulo (formerly FlexLend) is a DeFi savings platform for stablecoins on Solana. It automatically allocates deposits across integrated protocols to maximize yields while maintaining desired risk exposure.
Lulo(前身为 FlexLend)是 Solana 上面向稳定币的 DeFi 储蓄平台。它会自动在集成的协议间分配存款,在维持目标风险敞口的同时最大化收益。

Key Features

核心功能

FeatureDescription
Yield AggregationAutomatically routes deposits to highest-yielding protocols
Lulo ProtectBuilt-in smart contract risk protection (Protected/Boosted deposits)
Custom DepositsFull control over protocol allocation and risk parameters
Instant WithdrawalsNo lock-up periods (except 48h cooldown for Boosted)
Multi-ProtocolIntegrates Kamino, Drift, MarginFi, Jupiter
No CustodyFunds flow directly to integrated protocols, not held by Lulo
功能描述
收益聚合自动将存款路由至收益最高的协议
Lulo Protect内置智能合约风险保护(Protected/Boosted 存款)
自定义存款完全控制协议分配和风险参数
即时取款无锁定期(Boosted 存款除外,需48小时冷却期)
多协议支持集成 Kamino、Drift、MarginFi、Jupiter
非托管模式资金直接流向集成协议,不由 Lulo 持有

Why Use Lulo?

选择 Lulo 的理由

  • Automated Rebalancing: Checks rates hourly, automatically moves funds to better yields
  • Risk Management: Choose between Protected (insured), Boosted (higher yield), or Custom deposits
  • Zero Management Fees: Only 0.005 SOL one-time initialization fee
  • Multi-Reward Accrual: Earn rewards from multiple protocols from a single deposit
  • 9,400+ Lifetime Depositors with $34M+ in directed liquidity
  • 自动再平衡:每小时检查利率,自动将资金转移至收益更高的协议
  • 风险管理:可选择 Protected(受保)、Boosted(高收益)或自定义存款类型
  • 零管理费:仅需一次性支付0.005 SOL的初始化费用
  • 多奖励累积:单次存款即可从多个协议赚取奖励
  • 累计9400+存款用户,引导流动性超3400万美元

Overview

概览

Lulo provides three deposit types:
  • Protected Deposits: Stable yields with automatic coverage against protocol failures
  • Boosted Deposits: Higher yields by providing insurance for Protected deposits
  • Custom Deposits: Direct control over which protocols receive your funds
Lulo 提供三种存款类型:
  • Protected 存款:稳定收益,自动覆盖协议故障风险
  • Boosted 存款:通过为 Protected 存款提供保险获得更高收益
  • 自定义存款:直接控制资金流向的协议

Integrated Protocols

集成协议

ProtocolDescription
Kamino FinanceLending and liquidity vaults
Drift ProtocolPerpetuals and lending
MarginFiLending and borrowing
JupiterLending/earn features
协议描述
Kamino Finance借贷与流动性金库
Drift Protocol永续合约与借贷
MarginFi借贷服务
Jupiter借贷/赚币功能

Supported Tokens

支持的代币

  • Stablecoins: USDC, USDT, USDS, PYUSD
  • Native: SOL
  • LSTs: bSOL, JitoSOL, mSOL
  • Other: BONK, JUP, ORCA, COPE, CASH
Minimum Deposits: $100 for stablecoins, 1 SOL for native token

  • 稳定币:USDC、USDT、USDS、PYUSD
  • 原生代币:SOL
  • 流动性质押代币(LSTs):bSOL、JitoSOL、mSOL
  • 其他代币:BONK、JUP、ORCA、COPE、CASH
最低存款额:稳定币100美元,原生代币1 SOL

Quick Start

快速开始

API Authentication

API 认证

All API requests require a valid API key. Get your key from the Lulo Developer Dashboard.
typescript
const headers = {
  'Content-Type': 'application/json',
  'x-api-key': process.env.LULO_API_KEY,
};
所有 API 请求均需有效的 API 密钥。可从 Lulo 开发者控制台 获取密钥。
typescript
const headers = {
  'Content-Type': 'application/json',
  'x-api-key': process.env.LULO_API_KEY,
};

Base URLs

基础 URL

EnvironmentURL
Production
https://api.lulo.fi
Staging
https://staging.lulo.fi
Blinks
https://blink.lulo.fi
Developer Portal
https://dev.lulo.fi

环境URL
生产环境
https://api.lulo.fi
测试环境
https://staging.lulo.fi
Blinks
https://blink.lulo.fi
开发者门户
https://dev.lulo.fi

API Reference

API 参考

Generate Deposit Transaction

生成存款交易

Creates a serialized transaction for depositing tokens into Lulo.
Endpoint:
POST /v1/generate.transactions.deposit
Query Parameters:
ParameterTypeDescription
priorityFee
numberPriority fee in microlamports (e.g., 500000)
Request Body:
json
{
  "owner": "YourWalletPublicKey",
  "mintAddress": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "depositType": "protected",
  "amount": 100000000
}
Response:
json
{
  "transaction": "base64EncodedSerializedTransaction",
  "lastValidBlockHeight": 123456789
}
创建用于向 Lulo 存款的序列化交易。
端点
POST /v1/generate.transactions.deposit
查询参数:
参数类型描述
priorityFee
数字优先费用,单位为微lamports(例如:500000)
请求体:
json
{
  "owner": "YourWalletPublicKey",
  "mintAddress": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "depositType": "protected",
  "amount": 100000000
}
响应:
json
{
  "transaction": "base64EncodedSerializedTransaction",
  "lastValidBlockHeight": 123456789
}

Generate Withdrawal Transaction

生成取款交易

Creates a serialized transaction for withdrawing tokens from Lulo.
Endpoint:
POST /v1/generate.transactions.withdraw
Query Parameters:
ParameterTypeDescription
priorityFee
numberPriority fee in microlamports
Request Body:
json
{
  "owner": "YourWalletPublicKey",
  "mintAddress": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "withdrawType": "protected",
  "amount": 50000000
}
创建用于从 Lulo 取款的序列化交易。
端点
POST /v1/generate.transactions.withdraw
查询参数:
参数类型描述
priorityFee
数字优先费用,单位为微lamports
请求体:
json
{
  "owner": "YourWalletPublicKey",
  "mintAddress": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "withdrawType": "protected",
  "amount": 50000000
}

Get Account Data

获取账户数据

Retrieves user balances, interest earned, and APY metrics.
Endpoint:
GET /v1/account/{walletAddress}
Response:
json
{
  "totalDeposited": 1000000000,
  "totalInterestEarned": 5000000,
  "currentApy": 8.5,
  "positions": [
    {
      "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "depositType": "protected",
      "balance": 500000000,
      "interestEarned": 2500000,
      "apy": 7.2
    }
  ]
}
检索用户余额、已赚取利息和 APY 指标。
端点
GET /v1/account/{walletAddress}
响应:
json
{
  "totalDeposited": 1000000000,
  "totalInterestEarned": 5000000,
  "currentApy": 8.5,
  "positions": [
    {
      "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "depositType": "protected",
      "balance": 500000000,
      "interestEarned": 2500000,
      "apy": 7.2
    }
  ]
}

Get Pool Data

获取资金池数据

Returns current APY rates, liquidity amounts, and capacity metrics.
Endpoint:
GET /v1/pools
Response:
json
{
  "pools": [
    {
      "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "symbol": "USDC",
      "protectedApy": 6.5,
      "boostedApy": 9.2,
      "totalDeposited": 34000000000000,
      "availableCapacity": 10000000000000
    }
  ]
}
返回当前 APY 利率、流动性金额和容量指标。
端点
GET /v1/pools
响应:
json
{
  "pools": [
    {
      "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "symbol": "USDC",
      "protectedApy": 6.5,
      "boostedApy": 9.2,
      "totalDeposited": 34000000000000,
      "availableCapacity": 10000000000000
    }
  ]
}

Get Pending Withdrawals

获取待处理取款

Lists active withdrawal requests with cooldown periods.
Endpoint:
GET /v1/account/{walletAddress}/pending-withdrawals
列出处于冷却期的活跃取款请求。
端点
GET /v1/account/{walletAddress}/pending-withdrawals

Initialize Referrer

初始化推荐人账户

Sets up a referrer account for earning referral fees.
Endpoint:
POST /v1/referrer/initialize
设置推荐人账户以赚取推荐费。
端点
POST /v1/referrer/initialize

Claim Referral Rewards

领取推荐奖励

Processes referral fee claims.
Endpoint:
POST /v1/referrer/claim

处理推荐费领取。
端点
POST /v1/referrer/claim

Deposit Types Explained

存款类型说明

Protected Deposits

Protected 存款

Designed for risk-averse users seeking stable yields with automatic coverage.
How it works:
  1. Deposits earn interest from lending across integrated protocols
  2. A portion of interest is shared with Boosted depositors (protection fee)
  3. If a protocol fails, Boosted deposits cover Protected losses automatically
Benefits:
  • Lower risk with priority coverage
  • Stable, predictable yields
  • No claims to file - protection is automatic
  • Instant withdrawals
Coverage includes: Smart contract exploits, oracle failures, bad debt events
Not covered: Solana network failures, USDC depegging, Lulo contract failures
为风险厌恶型用户设计,提供稳定收益和自动风险覆盖。
工作原理:
  1. 存款通过在集成协议中借贷赚取利息
  2. 部分利息会分给 Boosted 存款用户(作为保护费用)
  3. 若协议出现故障,Boosted 存款将自动覆盖 Protected 存款的损失
优势:
  • 低风险,享有优先赔付权
  • 稳定、可预测的收益
  • 无需提交理赔申请——保护自动生效
  • 即时取款
覆盖范围:智能合约漏洞、预言机故障、坏账事件
不覆盖范围:Solana 网络故障、USDC 脱钩、Lulo 合约故障

Boosted Deposits

Boosted 存款

Higher yields in exchange for providing insurance to Protected depositors.
How it works:
  1. Earn lending yields from integrated protocols
  2. Receive additional yield from Protected deposit interest sharing
  3. Act as first-loss layer if a protocol fails
Benefits:
  • Higher APY (typically 1-2% more than Protected)
  • Dual income streams (lending + protection fees)
Risks:
  • First-loss position in case of protocol failures
  • 48-hour withdrawal cooldown
通过为 Protected 存款提供保险换取更高收益。
工作原理:
  1. 从集成协议的借贷中赚取收益
  2. 从 Protected 存款的利息分成中获得额外收益
  3. 协议故障时承担第一损失层
优势:
  • 更高的 APY(通常比 Protected 存款高1-2%)
  • 双重收入来源(借贷收益 + 保护费用)
风险:
  • 协议故障时承担第一损失
  • 取款需48小时冷却期

Custom Deposits

自定义存款

Full control over protocol allocation and risk parameters.
Features:
  • Select specific protocols (Kamino, Drift, MarginFi, Jupiter)
  • Set maximum exposure caps per protocol
  • Automatic reallocation when yields change
  • No protection coverage (direct protocol exposure)
Example: 50% max exposure with 3 protocols means no more than half your funds in any single protocol.

完全控制协议分配和风险参数。
功能:
  • 选择特定协议(Kamino、Drift、MarginFi、Jupiter)
  • 设置单协议最大敞口上限
  • 收益变化时自动重新分配资金
  • 无保护覆盖(直接暴露于协议风险)
示例:对3个协议设置50%的最大敞口,意味着任何单个协议中的资金占比不超过一半。

Integration Examples

集成示例

TypeScript: Deposit to Lulo

TypeScript:向 Lulo 存款

typescript
import { Connection, Transaction, VersionedTransaction, Keypair } from '@solana/web3.js';

const LULO_API_URL = 'https://api.lulo.fi';

interface DepositParams {
  owner: string;
  mintAddress: string;
  amount: number;
  depositType: 'protected' | 'boosted' | 'regular';
  priorityFee?: number;
}

async function generateDepositTransaction(params: DepositParams): Promise<string> {
  const { owner, mintAddress, amount, depositType, priorityFee = 500000 } = params;

  const response = await fetch(
    `${LULO_API_URL}/v1/generate.transactions.deposit?priorityFee=${priorityFee}`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': process.env.LULO_API_KEY!,
      },
      body: JSON.stringify({
        owner,
        mintAddress,
        depositType,
        amount,
      }),
    }
  );

  if (!response.ok) {
    throw new Error(`Deposit failed: ${response.statusText}`);
  }

  const data = await response.json();
  return data.transaction;
}

async function deposit(
  connection: Connection,
  wallet: Keypair,
  mintAddress: string,
  amount: number,
  depositType: 'protected' | 'boosted' | 'regular' = 'protected'
): Promise<string> {
  // Generate deposit transaction
  const serializedTx = await generateDepositTransaction({
    owner: wallet.publicKey.toBase58(),
    mintAddress,
    amount,
    depositType,
  });

  // Deserialize and sign
  const txBuffer = Buffer.from(serializedTx, 'base64');
  const transaction = VersionedTransaction.deserialize(txBuffer);
  transaction.sign([wallet]);

  // Send and confirm
  const signature = await connection.sendTransaction(transaction);
  await connection.confirmTransaction(signature, 'confirmed');

  console.log('Deposit successful:', signature);
  return signature;
}

// Usage
const connection = new Connection('https://api.mainnet-beta.solana.com');
const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';

await deposit(
  connection,
  wallet,
  USDC_MINT,
  100_000_000, // 100 USDC (6 decimals)
  'protected'
);
typescript
import { Connection, Transaction, VersionedTransaction, Keypair } from '@solana/web3.js';

const LULO_API_URL = 'https://api.lulo.fi';

interface DepositParams {
  owner: string;
  mintAddress: string;
  amount: number;
  depositType: 'protected' | 'boosted' | 'regular';
  priorityFee?: number;
}

async function generateDepositTransaction(params: DepositParams): Promise<string> {
  const { owner, mintAddress, amount, depositType, priorityFee = 500000 } = params;

  const response = await fetch(
    `${LULO_API_URL}/v1/generate.transactions.deposit?priorityFee=${priorityFee}`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': process.env.LULO_API_KEY!,
      },
      body: JSON.stringify({
        owner,
        mintAddress,
        depositType,
        amount,
      }),
    }
  );

  if (!response.ok) {
    throw new Error(`Deposit failed: ${response.statusText}`);
  }

  const data = await response.json();
  return data.transaction;
}

async function deposit(
  connection: Connection,
  wallet: Keypair,
  mintAddress: string,
  amount: number,
  depositType: 'protected' | 'boosted' | 'regular' = 'protected'
): Promise<string> {
  // Generate deposit transaction
  const serializedTx = await generateDepositTransaction({
    owner: wallet.publicKey.toBase58(),
    mintAddress,
    amount,
    depositType,
  });

  // Deserialize and sign
  const txBuffer = Buffer.from(serializedTx, 'base64');
  const transaction = VersionedTransaction.deserialize(txBuffer);
  transaction.sign([wallet]);

  // Send and confirm
  const signature = await connection.sendTransaction(transaction);
  await connection.confirmTransaction(signature, 'confirmed');

  console.log('Deposit successful:', signature);
  return signature;
}

// Usage
const connection = new Connection('https://api.mainnet-beta.solana.com');
const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';

await deposit(
  connection,
  wallet,
  USDC_MINT,
  100_000_000, // 100 USDC (6 decimals)
  'protected'
);

TypeScript: Withdraw from Lulo

TypeScript:从 Lulo 取款

typescript
interface WithdrawParams {
  owner: string;
  mintAddress: string;
  amount: number;
  withdrawType: 'protected' | 'boosted' | 'regular';
  priorityFee?: number;
}

async function generateWithdrawTransaction(params: WithdrawParams): Promise<string> {
  const { owner, mintAddress, amount, withdrawType, priorityFee = 500000 } = params;

  const response = await fetch(
    `${LULO_API_URL}/v1/generate.transactions.withdraw?priorityFee=${priorityFee}`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': process.env.LULO_API_KEY!,
      },
      body: JSON.stringify({
        owner,
        mintAddress,
        withdrawType,
        amount,
      }),
    }
  );

  if (!response.ok) {
    throw new Error(`Withdrawal failed: ${response.statusText}`);
  }

  const data = await response.json();
  return data.transaction;
}

async function withdraw(
  connection: Connection,
  wallet: Keypair,
  mintAddress: string,
  amount: number,
  withdrawType: 'protected' | 'boosted' | 'regular' = 'protected'
): Promise<string> {
  const serializedTx = await generateWithdrawTransaction({
    owner: wallet.publicKey.toBase58(),
    mintAddress,
    amount,
    withdrawType,
  });

  const txBuffer = Buffer.from(serializedTx, 'base64');
  const transaction = VersionedTransaction.deserialize(txBuffer);
  transaction.sign([wallet]);

  const signature = await connection.sendTransaction(transaction);
  await connection.confirmTransaction(signature, 'confirmed');

  console.log('Withdrawal successful:', signature);
  return signature;
}
typescript
interface WithdrawParams {
  owner: string;
  mintAddress: string;
  amount: number;
  withdrawType: 'protected' | 'boosted' | 'regular';
  priorityFee?: number;
}

async function generateWithdrawTransaction(params: WithdrawParams): Promise<string> {
  const { owner, mintAddress, amount, withdrawType, priorityFee = 500000 } = params;

  const response = await fetch(
    `${LULO_API_URL}/v1/generate.transactions.withdraw?priorityFee=${priorityFee}`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': process.env.LULO_API_KEY!,
      },
      body: JSON.stringify({
        owner,
        mintAddress,
        withdrawType,
        amount,
      }),
    }
  );

  if (!response.ok) {
    throw new Error(`Withdrawal failed: ${response.statusText}`);
  }

  const data = await response.json();
  return data.transaction;
}

async function withdraw(
  connection: Connection,
  wallet: Keypair,
  mintAddress: string,
  amount: number,
  withdrawType: 'protected' | 'boosted' | 'regular' = 'protected'
): Promise<string> {
  const serializedTx = await generateWithdrawTransaction({
    owner: wallet.publicKey.toBase58(),
    mintAddress,
    amount,
    withdrawType,
  });

  const txBuffer = Buffer.from(serializedTx, 'base64');
  const transaction = VersionedTransaction.deserialize(txBuffer);
  transaction.sign([wallet]);

  const signature = await connection.sendTransaction(transaction);
  await connection.confirmTransaction(signature, 'confirmed');

  console.log('Withdrawal successful:', signature);
  return signature;
}

TypeScript: Get Account Balance

TypeScript:获取账户余额

typescript
interface LuloPosition {
  mint: string;
  depositType: string;
  balance: number;
  interestEarned: number;
  apy: number;
}

interface LuloAccount {
  totalDeposited: number;
  totalInterestEarned: number;
  currentApy: number;
  positions: LuloPosition[];
}

async function getAccountData(walletAddress: string): Promise<LuloAccount> {
  const response = await fetch(
    `${LULO_API_URL}/v1/account/${walletAddress}`,
    {
      headers: {
        'x-api-key': process.env.LULO_API_KEY!,
      },
    }
  );

  if (!response.ok) {
    throw new Error(`Failed to fetch account: ${response.statusText}`);
  }

  return response.json();
}

// Usage
const account = await getAccountData(wallet.publicKey.toBase58());
console.log('Total Deposited:', account.totalDeposited);
console.log('Interest Earned:', account.totalInterestEarned);
console.log('Current APY:', account.currentApy);
typescript
interface LuloPosition {
  mint: string;
  depositType: string;
  balance: number;
  interestEarned: number;
  apy: number;
}

interface LuloAccount {
  totalDeposited: number;
  totalInterestEarned: number;
  currentApy: number;
  positions: LuloPosition[];
}

async function getAccountData(walletAddress: string): Promise<LuloAccount> {
  const response = await fetch(
    `${LULO_API_URL}/v1/account/${walletAddress}`,
    {
      headers: {
        'x-api-key': process.env.LULO_API_KEY!,
      },
    }
  );

  if (!response.ok) {
    throw new Error(`Failed to fetch account: ${response.statusText}`);
  }

  return response.json();
}

// Usage
const account = await getAccountData(wallet.publicKey.toBase58());
console.log('Total Deposited:', account.totalDeposited);
console.log('Interest Earned:', account.totalInterestEarned);
console.log('Current APY:', account.currentApy);

Using Solana Agent Kit

使用 Solana Agent Kit

typescript
import { SolanaAgentKit } from 'solana-agent-kit';

const agent = new SolanaAgentKit(
  privateKey,
  rpcUrl,
  openAiApiKey
);

// Lend USDC using Lulo (gets best APR)
const signature = await agent.methods.lendAssets(
  agent,
  100 // amount of USDC to lend
);

console.log('Lending transaction:', signature);
typescript
import { SolanaAgentKit } from 'solana-agent-kit';

const agent = new SolanaAgentKit(
  privateKey,
  rpcUrl,
  openAiApiKey
);

// Lend USDC using Lulo (gets best APR)
const signature = await agent.methods.lendAssets(
  agent,
  100 // amount of USDC to lend
);

console.log('Lending transaction:', signature);

Python: Lulo Integration

Python:Lulo 集成

python
import aiohttp
import os
from solders.keypair import Keypair
from solders.transaction import VersionedTransaction
from solana.rpc.async_api import AsyncClient
from solana.rpc.commitment import Confirmed
from solana.rpc.types import TxOpts
import base64

LULO_API_URL = "https://api.lulo.fi"
LULO_API_KEY = os.environ.get("LULO_API_KEY")

async def lulo_deposit(
    client: AsyncClient,
    wallet: Keypair,
    mint_address: str,
    amount: int,
    deposit_type: str = "protected"
) -> str:
    """Deposit tokens to Lulo for yield optimization."""

    async with aiohttp.ClientSession() as session:
        # Generate deposit transaction
        async with session.post(
            f"{LULO_API_URL}/v1/generate.transactions.deposit?priorityFee=500000",
            headers={
                "Content-Type": "application/json",
                "x-api-key": LULO_API_KEY,
            },
            json={
                "owner": str(wallet.pubkey()),
                "mintAddress": mint_address,
                "depositType": deposit_type,
                "amount": amount,
            }
        ) as response:
            if response.status != 200:
                raise Exception(f"Deposit failed: {await response.text()}")

            data = await response.json()
            tx_data = base64.b64decode(data["transaction"])

    # Deserialize, sign, and send
    transaction = VersionedTransaction.from_bytes(tx_data)
    transaction.sign([wallet])

    signature = await client.send_transaction(
        transaction,
        opts=TxOpts(preflight_commitment=Confirmed)
    )

    await client.confirm_transaction(signature.value, commitment="confirmed")

    return str(signature.value)

async def lulo_withdraw(
    client: AsyncClient,
    wallet: Keypair,
    mint_address: str,
    amount: int,
    withdraw_type: str = "protected"
) -> str:
    """Withdraw tokens from Lulo."""

    async with aiohttp.ClientSession() as session:
        async with session.post(
            f"{LULO_API_URL}/v1/generate.transactions.withdraw?priorityFee=500000",
            headers={
                "Content-Type": "application/json",
                "x-api-key": LULO_API_KEY,
            },
            json={
                "owner": str(wallet.pubkey()),
                "mintAddress": mint_address,
                "withdrawType": withdraw_type,
                "amount": amount,
            }
        ) as response:
            if response.status != 200:
                raise Exception(f"Withdrawal failed: {await response.text()}")

            data = await response.json()
            tx_data = base64.b64decode(data["transaction"])

    transaction = VersionedTransaction.from_bytes(tx_data)
    transaction.sign([wallet])

    signature = await client.send_transaction(
        transaction,
        opts=TxOpts(preflight_commitment=Confirmed)
    )

    await client.confirm_transaction(signature.value, commitment="confirmed")

    return str(signature.value)
python
import aiohttp
import os
from solders.keypair import Keypair
from solders.transaction import VersionedTransaction
from solana.rpc.async_api import AsyncClient
from solana.rpc.commitment import Confirmed
from solana.rpc.types import TxOpts
import base64

LULO_API_URL = "https://api.lulo.fi"
LULO_API_KEY = os.environ.get("LULO_API_KEY")

async def lulo_deposit(
    client: AsyncClient,
    wallet: Keypair,
    mint_address: str,
    amount: int,
    deposit_type: str = "protected"
) -> str:
    """Deposit tokens to Lulo for yield optimization."""

    async with aiohttp.ClientSession() as session:
        # Generate deposit transaction
        async with session.post(
            f"{LULO_API_URL}/v1/generate.transactions.deposit?priorityFee=500000",
            headers={
                "Content-Type": "application/json",
                "x-api-key": LULO_API_KEY,
            },
            json={
                "owner": str(wallet.pubkey()),
                "mintAddress": mint_address,
                "depositType": deposit_type,
                "amount": amount,
            }
        ) as response:
            if response.status != 200:
                raise Exception(f"Deposit failed: {await response.text()}")

            data = await response.json()
            tx_data = base64.b64decode(data["transaction"])

    # Deserialize, sign, and send
    transaction = VersionedTransaction.from_bytes(tx_data)
    transaction.sign([wallet])

    signature = await client.send_transaction(
        transaction,
        opts=TxOpts(preflight_commitment=Confirmed)
    )

    await client.confirm_transaction(signature.value, commitment="confirmed")

    return str(signature.value)

async def lulo_withdraw(
    client: AsyncClient,
    wallet: Keypair,
    mint_address: str,
    amount: int,
    withdraw_type: str = "protected"
) -> str:
    """Withdraw tokens from Lulo."""

    async with aiohttp.ClientSession() as session:
        async with session.post(
            f"{LULO_API_URL}/v1/generate.transactions.withdraw?priorityFee=500000",
            headers={
                "Content-Type": "application/json",
                "x-api-key": LULO_API_KEY,
            },
            json={
                "owner": str(wallet.pubkey()),
                "mintAddress": mint_address,
                "withdrawType": withdraw_type,
                "amount": amount,
            }
        ) as response:
            if response.status != 200:
                raise Exception(f"Withdrawal failed: {await response.text()}")

            data = await response.json()
            tx_data = base64.b64decode(data["transaction"])

    transaction = VersionedTransaction.from_bytes(tx_data)
    transaction.sign([wallet])

    signature = await client.send_transaction(
        transaction,
        opts=TxOpts(preflight_commitment=Confirmed)
    )

    await client.confirm_transaction(signature.value, commitment="confirmed")

    return str(signature.value)

Usage

Usage

async def main(): client = AsyncClient("https://api.mainnet-beta.solana.com") wallet = Keypair.from_base58_string("your-private-key")
USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"

# Deposit 100 USDC
signature = await lulo_deposit(
    client,
    wallet,
    USDC_MINT,
    100_000_000,  # 100 USDC
    "protected"
)
print(f"Deposit: {signature}")
undefined
async def main(): client = AsyncClient("https://api.mainnet-beta.solana.com") wallet = Keypair.from_base58_string("your-private-key")
USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"

# Deposit 100 USDC
signature = await lulo_deposit(
    client,
    wallet,
    USDC_MINT,
    100_000_000,  # 100 USDC
    "protected"
)
print(f"Deposit: {signature}")
undefined

Using Lulo Blinks

使用 Lulo Blinks

Lulo also supports Solana Actions/Blinks for simplified interactions:
typescript
// Blink endpoint for lending
const blinkUrl = `https://blink.lulo.fi/actions?amount=${amount}&symbol=USDC`;

// Fetch blink metadata
const response = await fetch(blinkUrl);
const blinkData = await response.json();

// Execute the action
const postResponse = await fetch(blinkUrl, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ account: walletAddress }),
});

const { transaction } = await postResponse.json();
// Sign and send transaction...

Lulo 还支持 Solana Actions/Blinks 以简化交互:
typescript
// Blink endpoint for lending
const blinkUrl = `https://blink.lulo.fi/actions?amount=${amount}&symbol=USDC`;

// Fetch blink metadata
const response = await fetch(blinkUrl);
const blinkData = await response.json();

// Execute the action
const postResponse = await fetch(blinkUrl, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ account: walletAddress }),
});

const { transaction } = await postResponse.json();
// Sign and send transaction...

Common Token Addresses

常用代币地址

TokenMint Address
USDC
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
USDT
Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB
USDS
USDSwr9ApdHk5bvJKMjzff41FfuX8bSxdKcR81vTwcA
PYUSD
2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo
SOL (Wrapped)
So11111111111111111111111111111111111111112
mSOL
mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So
JitoSOL
J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn
bSOL
bSo13r4TkiE4KumL71LsHTPpL2euBYLFx6h9HP3piy1

代币铸币地址
USDC
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
USDT
Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB
USDS
USDSwr9ApdHk5bvJKMjzff41FfuX8bSxdKcR81vTwcA
PYUSD
2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo
SOL(包装型)
So11111111111111111111111111111111111111112
mSOL
mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So
JitoSOL
J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn
bSOL
bSo13r4TkiE4KumL71LsHTPpL2euBYLFx6h9HP3piy1

Best Practices

最佳实践

Security

安全

  1. Never expose API keys - Use environment variables
  2. Validate transactions - Simulate before signing
  3. Set appropriate slippage - Account for rate changes
  4. Monitor positions - Regularly check balances and APY
  1. 切勿暴露 API 密钥 - 使用环境变量存储
  2. 验证交易 - 签名前先模拟交易
  3. 设置合理滑点 - 考虑利率变化
  4. 监控持仓 - 定期检查余额和 APY

Performance

性能

  1. Use priority fees - 500,000+ microlamports for faster confirmation
  2. Batch operations - Combine multiple operations when possible
  3. Cache pool data - Rates update hourly, cache appropriately
  1. 使用优先费用 - 500,000+微lamports以加快确认速度
  2. 批量操作 - 尽可能合并多个操作
  3. 缓存资金池数据 - 利率每小时更新,合理缓存

Error Handling

错误处理

typescript
try {
  const signature = await deposit(connection, wallet, USDC_MINT, amount, 'protected');
} catch (error) {
  if (error.message.includes('BAD_REQUEST')) {
    console.error('Invalid parameters');
  } else if (error.message.includes('UNAUTHORIZED')) {
    console.error('Invalid API key');
  } else if (error.message.includes('NOT_FOUND')) {
    console.error('Account or pool not found');
  } else {
    throw error;
  }
}
typescript
try {
  const signature = await deposit(connection, wallet, USDC_MINT, amount, 'protected');
} catch (error) {
  if (error.message.includes('BAD_REQUEST')) {
    console.error('参数无效');
  } else if (error.message.includes('UNAUTHORIZED')) {
    console.error('API密钥无效');
  } else if (error.message.includes('NOT_FOUND')) {
    console.error('账户或资金池不存在');
  } else {
    throw error;
  }
}

Monitoring APY

监控 APY

typescript
async function monitorRates(interval: number = 3600000) { // 1 hour
  setInterval(async () => {
    const pools = await fetch(`${LULO_API_URL}/v1/pools`, {
      headers: { 'x-api-key': process.env.LULO_API_KEY! },
    }).then(r => r.json());

    pools.pools.forEach(pool => {
      console.log(`${pool.symbol}: Protected ${pool.protectedApy}% | Boosted ${pool.boostedApy}%`);
    });
  }, interval);
}

typescript
async function monitorRates(interval: number = 3600000) { // 1小时
  setInterval(async () => {
    const pools = await fetch(`${LULO_API_URL}/v1/pools`, {
      headers: { 'x-api-key': process.env.LULO_API_KEY! },
    }).then(r => r.json());

    pools.pools.forEach(pool => {
      console.log(`${pool.symbol}: Protected ${pool.protectedApy}% | Boosted ${pool.boostedApy}%`);
    });
  }, interval);
}

Fee Structure

费用结构

Fee TypeAmountWhen
Initialization0.005 SOLFirst deposit only
ManagementNone-
WithdrawalNone-
TransactionVariablePer transaction (Solana fees)

费用类型金额收取时机
初始化费用0.005 SOL首次存款时
管理费-
取款费-
交易费可变每笔交易(Solana网络费用)

Resources

资源

Skill Structure

技能结构

lulo/
├── SKILL.md                      # This file
├── resources/
│   ├── api-reference.md          # Complete API documentation
│   └── token-addresses.md        # Supported token addresses
├── examples/
│   ├── deposit/
│   │   └── deposit.ts            # Deposit examples
│   ├── withdraw/
│   │   └── withdraw.ts           # Withdrawal examples
│   ├── balance/
│   │   └── balance.ts            # Balance query examples
│   └── integration/
│       └── full-integration.ts   # Complete integration example
├── templates/
│   └── lulo-client.ts            # Ready-to-use client template
└── docs/
    └── troubleshooting.md        # Common issues and solutions
lulo/
├── SKILL.md                      # 本文档
├── resources/
│   ├── api-reference.md          # 完整API文档
│   └── token-addresses.md        # 支持代币地址
├── examples/
│   ├── deposit/
│   │   └── deposit.ts            # 存款示例
│   ├── withdraw/
│   │   └── withdraw.ts           # 取款示例
│   ├── balance/
│   │   └── balance.ts            # 余额查询示例
│   └── integration/
│       └── full-integration.ts   # 完整集成示例
├── templates/
│   └── lulo-client.ts            # 即用型客户端模板
└── docs/
    └── troubleshooting.md        # 常见问题与解决方案