The Multiliquid Protocol on Solana can be integrated via the official TypeScript SDK, which provides a complete interface for quoting, building, and executing swaps against the on-chain program.
SDK Installation
Install and configure the TypeScript SDK
Pair Discovery
Find available trading pairs
Quoting
Get swap quotes using client-side math or simulation
Executing Swaps
Build and submit swap transactions
Ladder Pricing Model
Implement a rolling 24-hour laddered pricing model as an LP
The SDK provides a MultiliquidClient class that wraps all functionality:
import { Connection } from "@solana/web3.js";import { MultiliquidClient } from "@uniformlabs/multiliquid-svm-sdk";const connection = new Connection("https://api.mainnet-beta.solana.com");const client = new MultiliquidClient({ connection, cluster: "mainnet-beta", // "devnet" | "mainnet-beta" commitment: "confirmed", // optional, default: "confirmed"});
The cluster parameter determines which built-in pair registry is used. Both devnet and mainnet use the same program ID: FKeT8H2RSgsamrABNNxwT5f9g3n9msfm6D5AvocjrJAD.
The SDK ships with a hardcoded registry of known pairs for instant lookup:
const pairs = client.getPairs();// Returns all registered pairs for the configured cluster// Filter by assetconst usdcPairs = client.getPairs({ stableMint: new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"),});
Each returned entry includes the pair PDA, both mints, the liquidity provider, and token decimals:
for (const pair of pairs) { console.log(pair.assetSymbol); // e.g. "USTB" console.log(pair.pairAddress.toBase58()); console.log(pair.stableMint.toBase58()); console.log(pair.assetMint.toBase58()); console.log(pair.liquidityProvider.toBase58()); console.log(pair.stableDecimals); // e.g. 6 console.log(pair.assetDecimals); // e.g. 9}// Use the entry directly in swap paramsconst pair = pairs[0];const quote = await client.getQuote({ user: wallet.publicKey, liquidityProvider: pair.liquidityProvider, stableMint: pair.stableMint, assetMint: pair.assetMint, amount: new BN(1_000_000_000), swapDirection: SwapDirection.StableToAsset, swapType: SwapType.ExactIn,});
The SDK is instruction-first: the primary API returns TransactionInstruction objects for maximum composability. A convenience method for building full transactions is also available.
For more control, build the swap instruction separately and compose it with other instructions (e.g., compute budget):
import { ComputeBudgetProgram } from "@solana/web3.js";const { instruction, setupInstructions } = await client.buildSwapInstruction({ user: wallet.publicKey, liquidityProvider: LP, stableMint: USDC, assetMint: USTB, amount: new BN(1_000_000_000), swapDirection: SwapDirection.StableToAsset, swapType: SwapType.ExactIn, minAmountOut: new BN(990_000_000),});// setupInstructions contains ATA creation if needed (autoCreateAta defaults to true)// Compose with compute budget:const instructions = [ ComputeBudgetProgram.setComputeUnitLimit({ units: 150_000 }), ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 50_000 }), ...setupInstructions, instruction,];
The SDK does not include ComputeBudgetProgram instructions automatically. Set compute unit limits and priority fees based on your requirements. Use getQuoteViaSimulation() to measure actual compute units consumed.
The SDK provides structured error parsing for on-chain program errors:
try { const signature = await connection.sendTransaction(transaction); await connection.confirmTransaction(signature);} catch (error) { const parsed = client.parseSwapError(error); if (parsed) { console.log("Error:", parsed.name, "-", parsed.message); console.log("Category:", parsed.category); switch (parsed.category) { case "slippage": // AmountOutTooLow or AmountInTooHigh — re-quote with fresh state break; case "paused": // ProgramPaused, PairPaused, RwaPaused, StablePaused — wait or skip break; case "oracle": // InvalidNav — NAV source unavailable or divergent break; case "liquidity": // InsufficientLiquidity — try smaller amount or different pair break; case "input_validation": // Fix input parameters break; case "math": // MathOverflow/Underflow — trade may be too small or too large break; } }}