UNPKG

@solsdk/swapper_sdk

Version:

Solana Swap Library for Solana Tracker Swap API

678 lines (522 loc) 16.6 kB
# @solsdk/swapper_sdk > Efficient, type-safe, and developer-friendly library for integrating Solana-based token swaps into your TypeScript/JavaScript projects. ## Overview **@solsdk/swapper_sdk** provides a unified, high-performance API for executing token swaps on the Solana blockchain. It supports multiple DEXs, advanced fee and tip configuration, Jito bundle integration, and robust error handling. The library is strictly typed, follows modern best practices, and is suitable for both backend and frontend (browser) environments. --- ## Features - Unified Swap API for all major Solana DEXs - Strict TypeScript Typings (no `any`, no type assertions) - Jito Bundle Support for MEV protection - Custom Fee & Tip Logic (add/deduct, custom wallets, percentage) - Auto Priority Fee & Slippage calculation - Percentage & Full-Balance Swaps - Custom RPC Endpoints (Helius, Nextblock, etc.) - WebSocket & Polling Confirmations - Detailed Transaction Error Parsing - Connection Keep-Alive for custom endpoints - Resource Cleanup for long-running apps --- ## Installation ```bash npm install @solsdk/swapper_sdk # or yarn add @solsdk/swapper_sdk # or pnpm add @solsdk/swapper_sdk ``` --- ## Quick Start ```typescript import { Keypair } from "@solana/web3.js"; import bs58 from "bs58"; import { SolanaTracker } from "@solsdk/swapper_sdk"; const keypair = Keypair.fromSecretKey( bs58.decode("YOUR_SECRET_KEY") // Your wallet's secret key ); const solanaTracker = new SolanaTracker( keypair, "https://api.mainnet-beta.solana.com", // RPC endpoint "YOUR_API_KEY", // API key for swap instructions (optional) false // Debug mode (optional) ); async function swap() { // Get swap instructions const swapResponse = await solanaTracker.getSwapInstructions( "So11111111111111111111111111111111111111112", // From token (SOL) "4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R", // To token (RAY) 0.01, // Amount to swap (number, "auto", or "50%") 30, // Slippage (number or "auto") keypair.publicKey.toBase58(), // Payer public key "auto" // Priority fee (number or "auto") ); // Perform the swap try { const txid = await solanaTracker.performSwap(swapResponse, { sendOptions: { skipPreflight: true }, confirmationRetries: 30, confirmationRetryTimeout: 500, commitment: "processed", useWebSocket: true, }); console.log("Transaction ID:", txid); console.log("Transaction URL:", `https://solscan.io/tx/${txid}`); } catch (error) { console.error("Swap failed:", error.message); } } swap(); ``` --- ## API Reference ### Constructor ```typescript new SolanaTracker( keypair: Keypair, rpc: string, apiKey?: string, debug?: boolean = false ) ``` **Parameters:** - `keypair`: Solana wallet keypair (fee payer and signer) - `rpc`: Solana RPC endpoint (HTTP/HTTPS or WebSocket) - `apiKey`: Optional API key for swap instructions (empty string if not provided) - `debug`: Enable debug logging (default: false) --- ### getSwapInstructions ```typescript getSwapInstructions( from: string, to: string, fromAmount: number | string, slippage: number | "auto", payer: string, priorityFee?: number | "auto", forceLegacy?: boolean, additionalOptions?: SwapOptions ): Promise<SwapResponse> ``` **Parameters:** - `from`, `to`: Token mint addresses (base58 strings) - `fromAmount`: Amount to swap (`number`, `"auto"` for full balance, or `"50%"` for percentage) - `slippage`: Slippage percent (number) or `"auto"` - `payer`: Payer public key (base58 string) - `priorityFee`: Priority fee in SOL (number) or `"auto"` - `forceLegacy`: Force legacy transaction format (default: false, uses v0) - `additionalOptions`: Advanced swap configuration options **Returns:** Promise resolving to SwapResponse containing transaction data and rate information #### SwapOptions ```typescript interface SwapOptions { priorityFee?: number | "auto"; priorityFeeLevel?: | "min" | "low" | "medium" | "high" | "veryHigh" | "unsafeMax"; txVersion?: "v0" | "legacy"; fee?: FeeConfig; customTip?: CustomTip; feeType?: "add" | "deduct"; onlyDirectRoutes?: boolean; } interface FeeConfig { wallet: string; percentage: number; } interface CustomTip { wallet: string; amount: number; // in SOL } ``` --- ### getRate ```typescript getRate( from: string, to: string, amount: number | string | "auto", slippage: number | "auto" ): Promise<RateResponse> ``` **Parameters:** - `from`, `to`: Token mint addresses (base58 strings) - `amount`: Amount to check rate for (`number`, `"auto"`, or percentage string) - `slippage`: Slippage percent (number) or `"auto"` **Returns:** Promise resolving to RateResponse with pricing information --- ### performSwap ```typescript performSwap( swapResponse: SwapResponse, options?: TransactionSenderAndConfirmationWaiterOptions & { debug?: boolean; useWebSocket?: boolean; jito?: { enabled: boolean; tip: number }; } ): Promise<string> ``` **Parameters:** - `swapResponse`: Response from getSwapInstructions containing transaction data - `options`: Transaction execution and confirmation options **Returns:** Promise resolving to transaction signature (string) Executes the swap transaction with support for Jito bundles, WebSocket or polling confirmation, and custom send endpoints. --- ### performSwapWithDetails ```typescript performSwapWithDetails( swapResponse: SwapResponse, options?: TransactionSenderAndConfirmationWaiterOptions & { debug?: boolean; useWebSocket?: boolean; jito?: { enabled: boolean; tip: number }; } ): Promise<{ signature: string; error?: TransactionError }> ``` **Parameters:** - `swapResponse`: Response from getSwapInstructions containing transaction data - `options`: Transaction execution and confirmation options **Returns:** Promise resolving to object with signature and optional error details Same as `performSwap`, but returns detailed error information if the transaction fails instead of throwing. --- ### setCustomSendTransactionEndpoint ```typescript setCustomSendTransactionEndpoint( endpoint: string | null, headers?: Record<string, string> ): Promise<void> ``` **Parameters:** - `endpoint`: Custom RPC endpoint URL for sending transactions (null to clear) - `headers`: Optional custom headers to include with requests **Returns:** Promise that resolves when endpoint is configured Set a custom endpoint for sending transactions (e.g., Helius, Nextblock). Maintains a keep-alive connection for performance with automatic ping every 5 seconds. --- ### getTransactionDetails ```typescript getTransactionDetails(signature: string): Promise<ParsedTransactionWithMeta | null> ``` **Parameters:** - `signature`: Transaction signature to fetch details for **Returns:** Promise resolving to parsed transaction details or null if not found --- ### parseTransactionError ```typescript parseTransactionError(signature: string): Promise<TransactionError | null> ``` **Parameters:** - `signature`: Transaction signature to parse errors for **Returns:** Promise resolving to structured error information or null if no error --- ### Utility Methods #### setDebug ```typescript setDebug(enabled: boolean): void ``` Enable or disable debug logging. #### updateRpcEndpoint ```typescript updateRpcEndpoint(rpc: string): void ``` Change the main RPC endpoint. Creates new connection with WebSocket support. #### getCustomSendEndpoint ```typescript getCustomSendEndpoint(): string | null ``` Get the currently configured custom send endpoint. #### setBaseUrl ```typescript setBaseUrl(url: string): Promise<void> ``` Set the base URL for the swap API (default: https://swap-v2.solanatracker.io). #### destroy ```typescript destroy(): void ``` Clean up resources including keep-alive intervals and connections. Call this when done using the instance. --- ## Advanced Usage ### Swap Amount Options - **Swap full balance:** Pass `"auto"` as `fromAmount` - **Swap percentage:** Pass `"50%"` as `fromAmount` (any percentage like "25%", "75%") - **Specific amount:** Pass a number representing the token amount ### Priority Fee Configuration - **Auto priority fee:** Pass `"auto"` for `priorityFee` - **Priority fee levels:** Use `priorityFeeLevel` with values: `"min"`, `"low"`, `"medium"`, `"high"`, `"veryHigh"`, `"unsafeMax"` - **Manual fee:** Pass a number representing SOL amount ### Custom Fees and Tips - **Platform fees:** Use `fee: { wallet: "address", percentage: 0.25 }` in `SwapOptions` - **Custom tips:** Use `customTip: { wallet: "address", amount: 0.001 }` (amount in SOL) - **Fee handling:** Set `feeType: "add"` (add on top) or `"deduct"` (deduct from amount) ### Transaction Options - **Jito bundles:** Use `jito: { enabled: true, tip: 0.0001 }` in `performSwap` options - **Direct routes only:** Set `onlyDirectRoutes: true` in `SwapOptions` - **Transaction version:** Set `txVersion: "v0"` (default) or `"legacy"` - **WebSocket confirmation:** Set `useWebSocket: true` in `performSwap` options ### Custom RPC Endpoints ```typescript // Set custom send endpoint (e.g., Helius, Nextblock) await solanaTracker.setCustomSendTransactionEndpoint( "https://ams-sender.helius-rpc.com/fast", { Authorization: "Bearer YOUR_TOKEN" } ); // Clear custom endpoint await solanaTracker.setCustomSendTransactionEndpoint(null); ``` --- ## Error Handling The library provides comprehensive error handling with typed error objects: ```typescript // Method 1: Using try/catch with performSwap try { const txid = await solanaTracker.performSwap(swapResponse, options); console.log("Success:", txid); } catch (error) { console.error("Swap failed:", error.message); } // Method 2: Using performSwapWithDetails for structured errors const result = await solanaTracker.performSwapWithDetails( swapResponse, options ); if (result.error) { console.error("Error type:", result.error.type); console.error("Error message:", result.error.message); if (result.error.programId) { console.error("Failed program:", result.error.programId); } } else { console.log("Success:", result.signature); } // Method 3: Parse transaction errors manually const error = await solanaTracker.parseTransactionError(signature); if (error) { console.error(`${error.type}: ${error.message}`); } ``` ### TransactionError Types - `"InstructionError"`: Specific instruction failed - `"InsufficientFunds"`: Not enough funds for transaction - `"AccountNotFound"`: Required account not found - `"ProgramError"`: Program execution error - `"Unknown"`: Unrecognized error type --- ## Type Definitions ### Core Response Types ```typescript interface SwapResponse { txn: string; // Base64 encoded transaction txVersion: string; rate: RateResponse; forceLegacy?: boolean; type: "v0" | "legacy"; } interface RateResponse { amountIn: number; amountOut: number; minAmountOut: number; currentPrice: number; executionPrice: number; priceImpact: number; fee: number; baseCurrency: { decimals: number; mint: string }; quoteCurrency: { decimals: number; mint: string }; platformFee: number; platformFeeUI: number; rawQuoteResponse: any; } interface TransactionError { type: | "InstructionError" | "InsufficientFunds" | "AccountNotFound" | "ProgramError" | "Unknown"; message: string; instructionIndex?: number; programId?: string; rawError?: any; } ``` ### Transaction Options ```typescript interface TransactionSenderAndConfirmationWaiterOptions { sendOptions?: SendOptions; confirmationRetries?: number; confirmationRetryTimeout?: number; lastValidBlockHeightBuffer?: number; resendInterval?: number; confirmationCheckInterval?: number; skipConfirmationCheck?: boolean; commitment?: "processed" | "confirmed" | "finalized"; jito?: { enabled: boolean; tip: number }; } ``` --- ## Complete Examples ### Basic Token Swap ```typescript import { SolanaTracker } from "@solsdk/swapper_sdk"; import { Keypair } from "@solana/web3.js"; import bs58 from "bs58"; const solanaTracker = new SolanaTracker( "YOUR_API_KEY", "https://api.mainnet-beta.solana.com" ); const ownerKeypair = Keypair.fromSecretKey(bs58.decode("YOUR_PRIVATE_KEY")); // Get swap instructions const swapResponse = await solanaTracker.getSwapInstructions( "So11111111111111111111111111111111111111112", // SOL "4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R", // RAY 0.01, // 0.01 SOL 30, // 30% slippage ownerKeypair.publicKey.toString(), 0.0001 // Priority fee ); // Perform the swap const txid = await solanaTracker.performSwap(swapResponse, { sendOptions: { skipPreflight: false }, confirmationRetries: 30, confirmationRetryTimeout: 1000, lastValidBlockHeightBuffer: 150, commitment: "confirmed", resendInterval: 1000, confirmationCheckInterval: 1000, }); console.log("Transaction:", `https://solscan.io/tx/${txid}`); ``` ### Auto Priority Fee and Percentage Swap ```typescript // Swap 50% of SOL balance with auto priority fee const swapResponse = await solanaTracker.getSwapInstructions( "So11111111111111111111111111111111111111112", "4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R", "50%", // 50% of balance "auto", // Auto slippage ownerKeypair.publicKey.toString(), "auto" // Auto priority fee ); ``` ### Full Balance Swap with v0 Transaction ```typescript // Swap entire SOL balance using v0 transaction const swapResponse = await solanaTracker.getSwapInstructions( "So11111111111111111111111111111111111111112", "4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R", "auto", // Full balance 30, ownerKeypair.publicKey.toString(), 0.0001, { txVersion: "v0", onlyDirectRoutes: false, } ); ``` ### Swap with Custom Fees and Tips ```typescript const swapResponse = await solanaTracker.getSwapInstructions( "So11111111111111111111111111111111111111112", "4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R", 0.01, 30, ownerKeypair.publicKey.toString(), 0.0001, { fee: { wallet: "YOUR_FEE_WALLET_ADDRESS", percentage: 0.25, // 0.25% platform fee }, customTip: { wallet: "YOUR_TIP_WALLET_ADDRESS", amount: 0.001, // 0.001 SOL tip }, feeType: "add", // Add fee on top of swap amount } ); ``` ### Jito Bundle Transaction ```typescript const txid = await solanaTracker.performSwap(swapResponse, { sendOptions: { skipPreflight: false }, confirmationRetries: 30, jito: { enabled: true, tip: 0.0001, // 0.0001 SOL tip to Jito }, }); ``` ### WebSocket Confirmation ```typescript const txid = await solanaTracker.performSwap(swapResponse, { useWebSocket: true, confirmationRetries: 30, commitment: "confirmed", }); ``` ### Using Custom RPC Endpoints ```typescript // Set Helius fast endpoint await solanaTracker.setCustomSendTransactionEndpoint( "https://ams-sender.helius-rpc.com/fast", { Authorization: "Bearer YOUR_HELIUS_TOKEN" } ); // Set Nextblock endpoint await solanaTracker.setCustomSendTransactionEndpoint( "https://api.nextblock.dev/rpc", { "x-api-key": "YOUR_NEXTBLOCK_API_KEY" } ); // Clear custom endpoint (use default RPC) await solanaTracker.setCustomSendTransactionEndpoint(null); ``` ### Error Handling with Details ```typescript const result = await solanaTracker.performSwapWithDetails(swapResponse, { sendOptions: { skipPreflight: false }, confirmationRetries: 30, }); if (result.error) { switch (result.error.type) { case "InsufficientFunds": console.error("Not enough funds for this swap"); break; case "InstructionError": console.error( `Instruction ${result.error.instructionIndex} failed:`, result.error.message ); break; case "ProgramError": console.error( `Program ${result.error.programId} error:`, result.error.message ); break; default: console.error("Unknown error:", result.error.message); } } else { console.log("Swap successful:", result.signature); console.log("View transaction:", `https://solscan.io/tx/${result.signature}`); } ``` ### Resource Cleanup ```typescript // Always clean up resources when done solanaTracker.destroy(); ``` --- ## TypeScript Support - 100% strict TypeScript typings - No usage of `any` or type assertions in public API - All public interfaces and types are exported - Full IntelliSense support in modern IDEs - Comprehensive JSDoc documentation --- ## License MIT --- ## Contributing Pull requests and issues are welcome.