Claude-skill-registry-data lulo
Complete guide for Lulo - Solana's premier lending aggregator. Covers API integration for deposits, withdrawals, balance queries, Protected/Boosted deposits, Custom deposits, and automated yield optimization across Kamino, Drift, MarginFi, and Jupiter.
git clone https://github.com/majiayu000/claude-skill-registry-data
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry-data "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/lulo" ~/.claude/skills/majiayu000-claude-skill-registry-data-lulo && rm -rf "$T"
data/lulo/SKILL.mdLulo Development Guide
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.
What is 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.
Key Features
| Feature | Description |
|---|---|
| Yield Aggregation | Automatically routes deposits to highest-yielding protocols |
| Lulo Protect | Built-in smart contract risk protection (Protected/Boosted deposits) |
| Custom Deposits | Full control over protocol allocation and risk parameters |
| Instant Withdrawals | No lock-up periods (except 48h cooldown for Boosted) |
| Multi-Protocol | Integrates Kamino, Drift, MarginFi, Jupiter |
| No Custody | Funds flow directly to integrated protocols, not held by Lulo |
Why Use 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
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
Integrated Protocols
| Protocol | Description |
|---|---|
| Kamino Finance | Lending and liquidity vaults |
| Drift Protocol | Perpetuals and lending |
| MarginFi | Lending and borrowing |
| Jupiter | Lending/earn features |
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
Quick Start
API Authentication
All API requests require a valid API key. Get your key from the Lulo Developer Dashboard.
const headers = { 'Content-Type': 'application/json', 'x-api-key': process.env.LULO_API_KEY, };
Base URLs
| Environment | URL |
|---|---|
| Production | |
| Staging | |
| Blinks | |
| Developer Portal | |
API Reference
Generate Deposit Transaction
Creates a serialized transaction for depositing tokens into Lulo.
Endpoint:
POST /v1/generate.transactions.deposit
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| number | Priority fee in microlamports (e.g., 500000) |
Request Body:
{ "owner": "YourWalletPublicKey", "mintAddress": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "depositType": "protected", "amount": 100000000 }
Response:
{ "transaction": "base64EncodedSerializedTransaction", "lastValidBlockHeight": 123456789 }
Generate Withdrawal Transaction
Creates a serialized transaction for withdrawing tokens from Lulo.
Endpoint:
POST /v1/generate.transactions.withdraw
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| number | Priority fee in microlamports |
Request Body:
{ "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:
{ "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:
{ "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
Initialize Referrer
Sets up a referrer account for earning referral fees.
Endpoint:
POST /v1/referrer/initialize
Claim Referral Rewards
Processes referral fee claims.
Endpoint:
POST /v1/referrer/claim
Deposit Types Explained
Protected Deposits
Designed for risk-averse users seeking stable yields with automatic coverage.
How it works:
- Deposits earn interest from lending across integrated protocols
- A portion of interest is shared with Boosted depositors (protection fee)
- 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
Boosted Deposits
Higher yields in exchange for providing insurance to Protected depositors.
How it works:
- Earn lending yields from integrated protocols
- Receive additional yield from Protected deposit interest sharing
- 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
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.
Integration Examples
TypeScript: Deposit to Lulo
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
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
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
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
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 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}")
Using Lulo Blinks
Lulo also supports Solana Actions/Blinks for simplified interactions:
// 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
| Token | Mint Address |
|---|---|
| USDC | |
| USDT | |
| USDS | |
| PYUSD | |
| SOL (Wrapped) | |
| mSOL | |
| JitoSOL | |
| bSOL | |
Best Practices
Security
- Never expose API keys - Use environment variables
- Validate transactions - Simulate before signing
- Set appropriate slippage - Account for rate changes
- Monitor positions - Regularly check balances and APY
Performance
- Use priority fees - 500,000+ microlamports for faster confirmation
- Batch operations - Combine multiple operations when possible
- Cache pool data - Rates update hourly, cache appropriately
Error Handling
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; } }
Monitoring APY
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); }
Fee Structure
| Fee Type | Amount | When |
|---|---|---|
| Initialization | 0.005 SOL | First deposit only |
| Management | None | - |
| Withdrawal | None | - |
| Transaction | Variable | Per transaction (Solana fees) |
Resources
- Lulo App
- Documentation
- Developer Portal
- API Documentation
- Lulo Labs GitHub
- Lulo CPI Example
- Discord
- Telegram
- Twitter/X
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