
Trading Solana
- 18 installs
- 610 repo stars
- Updated June 26, 2026
- alsk1992/cloddsbot
trading-solana is a skill that swaps tokens on Solana DEXes using Jupiter, Raydium, Orca, Meteora, and Pump.fun.
About
This skill swaps tokens on Solana DEXes using the Jupiter aggregator plus Raydium, Orca, Meteora, and Pump.fun. It fetches quotes, executes swaps with slippage control, creates Jupiter limit orders and DCA schedules, discovers liquidity pools, and checks balances. A developer uses it to programmatically trade Solana tokens from the clodds bot.
- Swaps tokens on Solana via Jupiter, Raydium, Orca, Meteora, Pump.fun
- Jupiter limit orders and DCA (dollar-cost averaging)
- Pool discovery, quotes, and wallet balance checks
Trading Solana by the numbers
- 18 all-time installs (skills.sh)
- Ranked #725 of 1,106 Finance & Trading skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
trading-solana capabilities & compatibility
Requires SOLANA_PRIVATE_KEY; custom SOLANA_RPC_URL optional. On-chain fees apply.
- Capabilities
- dex swap · limit orders · dca · pool discovery · balance check
- Use cases
- trading
- Runs
- Runs locally
- Pricing
- Bring your own API key
What trading-solana says it does
Trade any token on Solana using Jupiter aggregator, Raydium, Orca Whirlpools, Meteora DLMM, and Pump.fun.
Create DCA - swap 100 USDC to JUP, 10 USDC every hour
npx skills add https://github.com/alsk1992/cloddsbot --skill trading-solanaAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 18 |
|---|---|
| repo stars | ★ 610 |
| Last updated | June 26, 2026 |
| Repository | alsk1992/cloddsbot ↗ |
What it does
Swap Solana tokens through Jupiter, Raydium, Orca, Meteora, and Pump.fun.
Who is it for?
Programmatic token swaps, limit orders, and DCA on Solana.
Skip if: EVM-chain swaps or prediction-market trading.
When should I use this skill?
You need to quote or execute a Solana swap, or set up a Jupiter limit order or DCA.
What you get
Executed Solana swaps plus optional limit orders and DCA schedules.
- Executed Solana swaps
- Jupiter limit orders and DCA schedules
By the numbers
- 5 Solana DEXes supported
- Jupiter DCA cycle minimum 30 seconds
Files
Solana DEX Trading - Complete API Reference
Trade any token on Solana using Jupiter aggregator, Raydium, Orca Whirlpools, Meteora DLMM, and Pump.fun.
Required Environment Variables
SOLANA_PRIVATE_KEY=base58_or_json_array # Your Solana wallet private key
SOLANA_RPC_URL=https://api.mainnet-beta.solana.com # Optional: custom RPC---
Chat Commands
Swaps
/sol swap <amount> <from> to <to> # Swap tokens on Solana
/sol swap 1 SOL to USDC # Swap 1 SOL to USDC
/sol swap 100 USDC to JUP # Swap 100 USDC to JUP
/sol swap 0.5 SOL to BONK # Swap 0.5 SOL to BONKQuotes
/sol quote <amount> <from> to <to> # Get swap quote without executing
/sol quote 1 SOL to USDC # Quote 1 SOL → USDCPool Discovery
/sol pools <token> # List liquidity pools for token
/sol pools SOL # All SOL pools
/sol pools BONK # All BONK poolsBalances & Wallet
/sol balance # Check SOL and token balances
/sol address # Show wallet address---
Supported DEXes
| DEX | Type | Features |
|---|---|---|
| Jupiter | Aggregator | Best route across all DEXes, limit orders, DCA |
| Raydium | AMM | Concentrated liquidity, high volume |
| Orca | Whirlpool | Concentrated liquidity pools, LP management |
| Meteora | DLMM | Dynamic liquidity market maker, LP management |
| Pump.fun | Launchpad | New token launches |
---
TypeScript API Reference
Jupiter (Aggregator - Recommended)
import {
executeJupiterSwap,
getJupiterQuote,
createJupiterLimitOrder,
cancelJupiterLimitOrder,
listJupiterLimitOrders,
createJupiterDCA,
closeJupiterDCA,
listJupiterDCAs,
} from 'clodds/solana/jupiter';
// Execute swap via Jupiter (best route)
const result = await executeJupiterSwap(connection, keypair, {
inputMint: 'So11111111111111111111111111111111111111112', // SOL
outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
amount: '1000000000', // 1 SOL in lamports
slippageBps: 50, // 0.5% slippage
});
console.log(`Swapped: ${result.inAmount} → ${result.outAmount}`);
console.log(`TX: ${result.signature}`);Jupiter Limit Orders
// Create limit order - sell 1 SOL for minimum 250 USDC
const order = await createJupiterLimitOrder(connection, keypair, {
inputMint: 'So11111111111111111111111111111111111111112',
outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
inAmount: '1000000000', // 1 SOL
outAmount: '250000000', // 250 USDC
expiredAtMs: Date.now() + 7 * 24 * 60 * 60 * 1000, // 1 week expiry
});
console.log(`Order created: ${order.orderPubKey}`);
// List open orders
const orders = await listJupiterLimitOrders(connection, keypair.publicKey.toBase58());
console.log(`Open orders: ${orders.length}`);
// Cancel order
await cancelJupiterLimitOrder(connection, keypair, order.orderPubKey);Jupiter DCA (Dollar Cost Averaging)
// Create DCA - swap 100 USDC to JUP, 10 USDC every hour
const dca = await createJupiterDCA(connection, keypair, {
inputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
outputMint: 'JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN', // JUP
inAmount: '100000000', // Total 100 USDC
inAmountPerCycle: '10000000', // 10 USDC per swap
cycleSecondsApart: 3600, // Every hour (min 30 seconds)
});
console.log(`DCA created: ${dca.dcaPubKey}`);
// List active DCAs
const dcas = await listJupiterDCAs(connection, keypair.publicKey.toBase58());
// Close DCA and withdraw remaining funds
await closeJupiterDCA(connection, keypair, dca.dcaPubKey);Raydium
import {
executeRaydiumSwap,
getRaydiumQuote,
listRaydiumPools,
getClmmPositions,
createClmmPosition,
increaseClmmLiquidity,
decreaseClmmLiquidity,
closeClmmPosition,
harvestClmmRewards,
addAmmLiquidity,
removeAmmLiquidity,
} from 'clodds/solana/raydium';
// Get quote
const quote = await getRaydiumQuote({
inputMint: 'SOL',
outputMint: 'USDC',
amount: 1_000_000_000,
});
console.log(`Expected output: ${quote.outAmount}`);
// Execute swap
const result = await executeRaydiumSwap(connection, keypair, {
inputMint: 'So11111111111111111111111111111111111111112',
outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
amount: '1000000000',
slippageBps: 50,
});
// List pools
const pools = await listRaydiumPools({ tokenMints: ['So11111111111111111111111111111111111111112'] });
// CLMM: Open concentrated liquidity position
const position = await createClmmPosition(connection, keypair, {
poolId: 'POOL_ID_HERE',
priceLower: 100,
priceUpper: 200,
baseAmount: '1000000000',
});
// CLMM: List positions
const positions = await getClmmPositions(connection, keypair);
// CLMM: Harvest rewards
const rewards = await harvestClmmRewards(connection, keypair);
// AMM: Add liquidity
await addAmmLiquidity(connection, keypair, {
poolId: 'AMM_POOL_ID',
amountA: '1000000000',
fixedSide: 'a',
});Orca Whirlpools
import { executeOrcaWhirlpoolSwap, getOrcaWhirlpoolQuote, listOrcaWhirlpoolPools } from 'clodds/solana/orca';
// Get quote
const quote = await getOrcaWhirlpoolQuote({
inputMint: 'SOL',
outputMint: 'USDC',
amount: 1_000_000_000,
});
// Execute swap
const result = await executeOrcaWhirlpoolSwap({
inputMint: 'SOL',
outputMint: 'USDC',
amount: 1_000_000_000,
slippage: 0.5,
});
// List pools
const pools = await listOrcaWhirlpoolPools({ token: 'SOL' });Meteora DLMM
import { executeMeteoraDlmmSwap, getMeteoraDlmmQuote, listMeteoraDlmmPools } from 'clodds/solana/meteora';
// Get quote
const quote = await getMeteoraDlmmQuote({
inputMint: 'SOL',
outputMint: 'USDC',
amount: 1_000_000_000,
});
// Execute swap
const result = await executeMeteoraDlmmSwap({
inputMint: 'SOL',
outputMint: 'USDC',
amount: 1_000_000_000,
slippage: 0.5,
});
// List pools
const pools = await listMeteoraDlmmPools({ token: 'SOL' });Pump.fun
import {
executePumpFunTrade,
getBondingCurveState,
getTokenPriceInfo,
calculateBuyQuote,
calculateSellQuote,
isGraduated,
getTokenInfo,
getPumpPortalQuote,
} from 'clodds/solana/pumpapi';
// Buy token on Pump.fun
const result = await executePumpFunTrade(connection, keypair, {
mint: 'token_mint_address',
action: 'buy',
amount: 0.1, // SOL amount
denominatedInSol: true,
slippageBps: 500, // 5% slippage for volatile tokens
});
// Sell token
const result = await executePumpFunTrade(connection, keypair, {
mint: 'token_mint_address',
action: 'sell',
amount: 1000000, // Token amount
denominatedInSol: false,
slippageBps: 500,
});On-Chain Bonding Curve
import BN from 'bn.js';
// Get bonding curve state directly from chain
const state = await getBondingCurveState(connection, 'token_mint');
if (state) {
console.log(`Virtual SOL: ${state.virtualSolReserves.toString()}`);
console.log(`Virtual Tokens: ${state.virtualTokenReserves.toString()}`);
console.log(`Graduated: ${state.complete}`);
}
// Get comprehensive price info
const priceInfo = await getTokenPriceInfo(connection, 'token_mint', 200); // 200 = SOL price USD
console.log(`Price: ${priceInfo.priceInSol} SOL ($${priceInfo.priceInUsd})`);
console.log(`Market Cap: $${priceInfo.marketCapUsd}`);
console.log(`Bonding Progress: ${(priceInfo.bondingProgress * 100).toFixed(1)}%`);
// Calculate buy quote with price impact
const solAmount = new BN(0.5 * 1e9); // 0.5 SOL in lamports
const buyQuote = calculateBuyQuote(state, solAmount, 100); // 1% fee
console.log(`Tokens out: ${buyQuote.tokensOut.toNumber() / 1e6}`);
console.log(`Price impact: ${buyQuote.priceImpact.toFixed(2)}%`);
// Calculate sell quote
const tokenAmount = new BN(1000000 * 1e6); // 1M tokens
const sellQuote = calculateSellQuote(state, tokenAmount, 100);
console.log(`SOL out: ${sellQuote.solOut.toNumber() / 1e9}`);
// Check if token graduated to PumpSwap
const graduation = await isGraduated(connection, 'token_mint');
if (graduation.graduated) {
console.log(`PumpSwap pool: ${graduation.pumpswapPool}`);
}PumpPortal Quote API
// Get quote from PumpPortal (supports pump and raydium pools)
const quote = await getPumpPortalQuote({
mint: 'token_mint',
action: 'buy',
amount: '0.5', // 0.5 SOL
pool: 'auto', // pump, raydium, or auto
});
console.log(`Input: ${quote.inputAmount}, Output: ${quote.outputAmount}`);Token Resolution
import { resolveTokenMints, getTokenList } from 'clodds/solana/tokenlist';
// Resolve token symbols to mint addresses
const mints = await resolveTokenMints(['SOL', 'USDC', 'JUP', 'BONK']);
// ['So111...', 'EPjF...', '...', '...']
// Get full token list
const tokens = await getTokenList();Pool Discovery
import { listAllPools, selectBestPool } from 'clodds/solana/pools';
// List all pools for a token pair
const pools = await listAllPools({
inputMint: 'SOL',
outputMint: 'USDC',
});
// Select best pool based on liquidity
const best = await selectBestPool({
inputMint: 'SOL',
outputMint: 'USDC',
amount: 1_000_000_000,
});Wallet Utilities
import { loadSolanaKeypair, getSolanaConnection, signAndSendTransaction } from 'clodds/solana/wallet';
// Load keypair from env
const keypair = loadSolanaKeypair();
// Get connection
const connection = getSolanaConnection();
// Sign and send transaction
const signature = await signAndSendTransaction(connection, transaction, keypair);---
Token Symbols
Common token symbols that can be used:
| Symbol | Name | Mint Address |
|---|---|---|
| SOL | Solana | So11111111111111111111111111111111111111112 |
| USDC | USD Coin | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
| USDT | Tether | Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB |
| JUP | Jupiter | JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN |
| BONK | Bonk | DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263 |
| WIF | dogwifhat | EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm |
| PYTH | Pyth | HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3 |
---
Slippage Settings
| Token Type | Recommended Slippage |
|---|---|
| Major (SOL, USDC) | 0.5% |
| Mid-cap | 1-2% |
| Small-cap / Meme | 3-5% |
| New launches | 5-10% |
---
Error Handling
import { SolanaSwapError, InsufficientBalanceError, SlippageExceededError } from 'clodds/solana';
try {
await executeJupiterSwap({ ... });
} catch (error) {
if (error instanceof InsufficientBalanceError) {
console.log('Not enough balance');
} else if (error instanceof SlippageExceededError) {
console.log('Price moved too much, increase slippage');
}
}/**
* Solana DEX Trading CLI Skill
*
* Commands:
* /sol swap <amount> <from> to <to> - Execute swap
* /sol quote <amount> <from> to <to> - Get quote
* /sol pools <token> - List pools for token
* /sol balance - Check balances
* /sol address - Show wallet address
* /sol route <from> <to> - Find best route
*/
import { logger } from '../../../utils/logger';
// Lazy load Solana modules
const getSolanaModules = async () => {
const [wallet, jupiter, raydium, orca, meteora, pools, tokenlist] = await Promise.all([
import('../../../solana/wallet'),
import('../../../solana/jupiter'),
import('../../../solana/raydium'),
import('../../../solana/orca'),
import('../../../solana/meteora'),
import('../../../solana/pools'),
import('../../../solana/tokenlist'),
]);
return { wallet, jupiter, raydium, orca, meteora, pools, tokenlist };
};
function isConfigured(): boolean {
return !!(process.env.SOLANA_PRIVATE_KEY || process.env.SOLANA_KEYPAIR_PATH);
}
async function handleAddress(): Promise<string> {
if (!isConfigured()) {
return 'Solana wallet not configured. Set SOLANA_PRIVATE_KEY or SOLANA_KEYPAIR_PATH.';
}
try {
const { wallet } = await getSolanaModules();
const keypair = wallet.loadSolanaKeypair();
return `**Solana Wallet**\n\nAddress: \`${keypair.publicKey.toBase58()}\``;
} catch (error) {
return `Error loading wallet: ${error instanceof Error ? error.message : String(error)}`;
}
}
async function handleBalance(): Promise<string> {
if (!isConfigured()) {
return 'Solana wallet not configured. Set SOLANA_PRIVATE_KEY or SOLANA_KEYPAIR_PATH.';
}
try {
const { wallet } = await getSolanaModules();
const connection = wallet.getSolanaConnection();
const keypair = wallet.loadSolanaKeypair();
const balance = await connection.getBalance(keypair.publicKey);
const solBalance = balance / 1e9;
return `**Solana Balances**\n\n` +
`Address: \`${keypair.publicKey.toBase58()}\`\n` +
`SOL: ${solBalance.toFixed(4)}`;
} catch (error) {
return `Error fetching balance: ${error instanceof Error ? error.message : String(error)}`;
}
}
async function handleSwap(args: string[]): Promise<string> {
if (!isConfigured()) {
return 'Solana wallet not configured. Set SOLANA_PRIVATE_KEY or SOLANA_KEYPAIR_PATH.';
}
// Parse: <amount> <from> to <to>
const toIndex = args.findIndex(a => a.toLowerCase() === 'to');
if (toIndex < 2 || toIndex >= args.length - 1) {
return 'Usage: /sol swap <amount> <from> to <to>\nExample: /sol swap 1 SOL to USDC';
}
const amount = args[0];
const fromToken = args.slice(1, toIndex).join(' ');
const toToken = args.slice(toIndex + 1).join(' ');
try {
const { wallet, jupiter, tokenlist } = await getSolanaModules();
const keypair = wallet.loadSolanaKeypair();
const connection = wallet.getSolanaConnection();
// Resolve token symbols to mint addresses
const [fromMint, toMint] = await tokenlist.resolveTokenMints([fromToken, toToken]);
if (!fromMint || !toMint) {
return `Could not resolve token symbols. Use mint addresses or common symbols like SOL, USDC, JUP.`;
}
// Use Jupiter aggregator for best route
const result = await jupiter.executeJupiterSwap(connection, keypair, {
inputMint: fromMint,
outputMint: toMint,
amount,
slippageBps: 50, // 0.5% default
});
return `**Swap Executed**\n\n` +
`From: ${fromToken}\n` +
`To: ${toToken}\n` +
`Amount In: ${result.inAmount}\n` +
`Amount Out: ${result.outAmount}\n` +
`Price Impact: ${result.priceImpactPct || 'N/A'}%\n` +
`TX: \`${result.signature}\``;
} catch (error) {
return `Swap failed: ${error instanceof Error ? error.message : String(error)}`;
}
}
async function handleQuote(args: string[]): Promise<string> {
// Parse: <amount> <from> to <to>
const toIndex = args.findIndex(a => a.toLowerCase() === 'to');
if (toIndex < 2 || toIndex >= args.length - 1) {
return 'Usage: /sol quote <amount> <from> to <to>\nExample: /sol quote 1 SOL to USDC';
}
const amount = args[0];
const fromToken = args.slice(1, toIndex).join(' ');
const toToken = args.slice(toIndex + 1).join(' ');
try {
const { wallet, raydium, orca, meteora, pools, tokenlist } = await getSolanaModules();
const connection = wallet.getSolanaConnection();
// Resolve tokens
const [fromMint, toMint] = await tokenlist.resolveTokenMints([fromToken, toToken]);
if (!fromMint || !toMint) {
return `Could not resolve token symbols.`;
}
// Get quotes from multiple DEXes
const quotes: Array<{ dex: string; outAmount: string; priceImpact?: string }> = [];
try {
const rayQuote = await raydium.getRaydiumQuote({
inputMint: fromMint,
outputMint: toMint,
amount,
});
if (rayQuote?.outAmount) quotes.push({ dex: 'Raydium', outAmount: rayQuote.outAmount, priceImpact: rayQuote.priceImpact?.toString() });
} catch { /* skip */ }
// Find best pool and get quote
const allPools = await pools.listAllPools(connection, {
tokenMints: [fromMint, toMint],
limit: 10,
});
for (const pool of allPools.slice(0, 3)) {
try {
if (pool.dex === 'meteora') {
const quote = await meteora.getMeteoraDlmmQuote(connection, {
poolAddress: pool.address,
inputMint: fromMint,
inAmount: amount,
});
if (quote) quotes.push({ dex: 'Meteora', outAmount: quote.outAmount });
} else if (pool.dex === 'orca') {
const quote = await orca.getOrcaWhirlpoolQuote({
poolAddress: pool.address,
inputMint: fromMint,
amount,
});
if (quote) quotes.push({ dex: 'Orca', outAmount: quote.amountOut });
}
} catch { /* skip */ }
}
if (quotes.length === 0) {
return `No quotes available for ${fromToken} -> ${toToken}`;
}
let output = `**Swap Quotes: ${amount} ${fromToken} -> ${toToken}**\n\n`;
for (const q of quotes) {
output += `**${q.dex}**: ${q.outAmount} ${toToken}`;
if (q.priceImpact) output += ` (impact: ${q.priceImpact}%)`;
output += '\n';
}
return output;
} catch (error) {
return `Quote failed: ${error instanceof Error ? error.message : String(error)}`;
}
}
async function handlePools(token: string): Promise<string> {
if (!token) {
return 'Usage: /sol pools <token>\nExample: /sol pools SOL';
}
try {
const { wallet, pools, tokenlist } = await getSolanaModules();
const connection = wallet.getSolanaConnection();
// Resolve token
const [mint] = await tokenlist.resolveTokenMints([token]);
if (!mint) {
return `Could not resolve token: ${token}`;
}
const allPools = await pools.listAllPools(connection, {
tokenMints: [mint],
limit: 20,
});
if (allPools.length === 0) {
return `No pools found for ${token}`;
}
let output = `**Pools for ${token}** (${allPools.length} found)\n\n`;
for (const pool of allPools.slice(0, 15)) {
output += `**${pool.dex}**: ${pool.tokenMintA?.slice(0, 8) || 'A'}/${pool.tokenMintB?.slice(0, 8) || 'B'}\n`;
output += ` Address: \`${pool.address.slice(0, 12)}...\`\n`;
if (pool.liquidity) output += ` Liquidity: $${pool.liquidity.toLocaleString()}\n`;
if (pool.volume24h) output += ` 24h Volume: $${pool.volume24h.toLocaleString()}\n`;
output += '\n';
}
return output;
} catch (error) {
return `Error fetching pools: ${error instanceof Error ? error.message : String(error)}`;
}
}
async function handleRoute(from: string, to: string): Promise<string> {
if (!from || !to) {
return 'Usage: /sol route <from> <to>\nExample: /sol route SOL USDC';
}
try {
const { wallet, pools, tokenlist } = await getSolanaModules();
const connection = wallet.getSolanaConnection();
const [fromMint, toMint] = await tokenlist.resolveTokenMints([from, to]);
if (!fromMint || !toMint) {
return `Could not resolve tokens: ${from}, ${to}`;
}
const best = await pools.selectBestPool(connection, {
tokenMints: [fromMint, toMint],
sortBy: 'liquidity',
});
if (!best) {
return `No route found for ${from} -> ${to}`;
}
return `**Best Route: ${from} -> ${to}**\n\n` +
`DEX: ${best.dex || 'Unknown'}\n` +
`Pool: \`${best.address || 'Unknown'}\`\n` +
`Liquidity: $${(best.liquidity ?? 0).toLocaleString()}\n` +
`24h Volume: $${(best.volume24h ?? 0).toLocaleString()}`;
} catch (error) {
return `Error finding route: ${error instanceof Error ? error.message : String(error)}`;
}
}
async function handleDex(dex: string, subCommand: string, args: string[]): Promise<string> {
const dexName = dex.toLowerCase();
if (!['raydium', 'orca', 'meteora', 'ray', 'met'].includes(dexName)) {
return `Unknown DEX: ${dex}. Use raydium, orca, or meteora.`;
}
if (subCommand === 'pools') {
const token = args[0];
if (!token) return `Usage: /sol ${dex} pools <token>`;
try {
const { wallet, raydium, orca, meteora, tokenlist } = await getSolanaModules();
const connection = wallet.getSolanaConnection();
const [mint] = await tokenlist.resolveTokenMints([token]);
if (!mint) return `Could not resolve token: ${token}`;
let pools: Array<{ address?: string; id?: string; liquidity?: number; volume24h?: number }> = [];
if (dexName === 'raydium' || dexName === 'ray') {
pools = await raydium.listRaydiumPools({ tokenMints: [mint], limit: 10 });
} else if (dexName === 'orca') {
pools = await orca.listOrcaWhirlpoolPools({ tokenMints: [mint], limit: 10 });
} else if (dexName === 'meteora' || dexName === 'met') {
pools = await meteora.listMeteoraDlmmPools(connection, { tokenMints: [mint], limit: 10 });
}
if (pools.length === 0) {
return `No ${dex} pools found for ${token}`;
}
let output = `**${dex} Pools for ${token}**\n\n`;
for (const pool of pools.slice(0, 10)) {
const poolAddr = pool.address || pool.id || 'Unknown';
output += `Address: \`${poolAddr.slice(0, 20)}...\`\n`;
if (pool.liquidity) output += ` Liquidity: $${pool.liquidity.toLocaleString()}\n`;
output += '\n';
}
return output;
} catch (error) {
return `Error: ${error instanceof Error ? error.message : String(error)}`;
}
}
return `Usage: /sol ${dex} pools <token>`;
}
export async function execute(args: string): Promise<string> {
const parts = args.trim().split(/\s+/);
const command = parts[0]?.toLowerCase() || 'help';
const rest = parts.slice(1);
try {
switch (command) {
case 'swap':
return handleSwap(rest);
case 'quote':
return handleQuote(rest);
case 'pools':
return handlePools(rest.join(' '));
case 'balance':
case 'bal':
return handleBalance();
case 'address':
case 'wallet':
return handleAddress();
case 'route':
return handleRoute(rest[0], rest[1]);
case 'raydium':
case 'ray':
return handleDex('Raydium', rest[0], rest.slice(1));
case 'orca':
return handleDex('Orca', rest[0], rest.slice(1));
case 'meteora':
case 'met':
return handleDex('Meteora', rest[0], rest.slice(1));
case 'help':
default:
return `**Solana DEX Trading**
**Swaps:**
/sol swap <amount> <from> to <to> Execute swap (uses Jupiter)
/sol quote <amount> <from> to <to> Get quotes from all DEXes
**Pool Discovery:**
/sol pools <token> List all pools for token
/sol route <from> <to> Find best route
**DEX-Specific:**
/sol raydium pools <token> Raydium pools
/sol orca pools <token> Orca Whirlpools
/sol meteora pools <token> Meteora DLMM pools
**Wallet:**
/sol balance Check SOL balance
/sol address Show wallet address
**Examples:**
/sol swap 1 SOL to USDC
/sol quote 100 USDC to JUP
/sol pools BONK
/sol route SOL USDC`;
}
} catch (error) {
logger.error({ error, args }, 'Solana skill error');
return `Error: ${error instanceof Error ? error.message : String(error)}`;
}
}
export default {
name: 'trading-solana',
description: 'Solana DEX trading - swap, quote, pools, routes across Jupiter, Raydium, Orca, and Meteora',
commands: ['/sol', '/trade-sol', '/tradesol'],
handle: execute,
};
Related skills
FAQ
Which DEXes are supported?
Jupiter (aggregator), Raydium, Orca Whirlpools, Meteora DLMM, and Pump.fun.
Does it support recurring buys?
Yes, Jupiter DCA lets you swap a total amount in fixed cycles (min 30 seconds apart).