@solsdk/swapper_sdk
Version:
Solana Swap Library for Solana Tracker Swap API
678 lines (522 loc) • 16.6 kB
Markdown
# @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.