onetrade-sdk
v0.2.0
Published
OneTrade Solana Unified Trading SDK
Readme
OneTrade SDK
A unified Solana trading SDK with a clean, consistent interface for executing trades across multiple DEX protocols.
Features
- Unified API - Consistent interface across multiple DEX protocols
- MEV Protection - Jito bundle support for frontrunning protection
- Flexible Execution - Choose between Jito bundles or standard RPC
- Automatic Token Detection - Handles both Token and Token-2022 programs
- V0 Transaction Support - Modern versioned transactions with lookup tables
- Outcome Parsing - Automatic transaction log parsing to extract trade results
- TypeScript First - Full type safety with precise interfaces
Supported Protocols
| Protocol | Description | Buy | Sell | Quote |
|----------|-------------|-----|------|-------|
| pumpfun | Pump.fun bonding curve | exactIn | exactIn | Yes |
| pumpswap | Pump.fun AMM (migrated tokens) | exactIn | exactIn | Yes |
| bonkfun | Bonk.fun launchpad (Raydium LaunchLab) | exactIn | exactIn | Yes |
| bonkers | Bonkers launchpad (Raydium LaunchLab) | exactIn | exactIn | Yes |
| moonshot | Moonshot launchpad (Meteora DBC) | exactIn | exactIn | Yes |
| moonit | Moonit bonding curve | exactIn | exactIn | Yes |
| daosfun | DAOs.fun launchpad (Meteora DBC) | exactIn | exactIn | Yes |
| jupiterstudio | Jupiter Studio launchpad (Meteora DBC) | exactIn | exactIn | Yes |
| raydiumlaunchlab | Raydium LaunchLab (generic) | exactIn | exactIn | Yes |
| bagsfm | Bags.fm launchpad (Meteora DBC) | exactIn | exactIn | Yes |
| meteoravirtualcurve | Meteora Virtual Curve (generic) | exactIn | exactIn | Yes |
| raydiumcpmm | Raydium CPMM pools | exactIn | exactIn | Yes |
Installation
pnpm add onetrade-sdkQuick Start
import { Connection, Keypair } from "@solana/web3.js";
import { OneTrade, PumpfunAdapter, JitoExecutor } from "onetrade-sdk";
import bs58 from "bs58";
// Setup
const connection = new Connection(process.env.RPC_URL);
const signer = Keypair.fromSecretKey(bs58.decode(process.env.PRIVATE_KEY));
const jitoAuth = Keypair.fromSecretKey(bs58.decode(process.env.JITO_AUTH_PRIVATE_KEY));
// Initialize executor
const jitoExecutor = new JitoExecutor({
connection,
config: {
region: "ny",
authKeypair: jitoAuth,
tipLamports: 1_000_000,
},
});
// Initialize OneTrade
const onetrade = new OneTrade({
connection,
adapters: [new PumpfunAdapter(connection)],
executors: [jitoExecutor],
});
// Execute a trade
const result = await onetrade.trade(
{
protocol: "pumpfun",
side: "buy",
mint: new PublicKey("GMUedQYdP6UubueYm32Qx6ceK3dniNgTTFWzxBYRpump"),
amountType: "exactIn",
amount: 10_000_000n, // 0.01 SOL in lamports
slippagePercent: 5,
signer,
},
{ executor: "jito", confirmation: "confirmed" }
);
console.log(`Spent ${result.solSpentFloat} SOL`);
console.log(`Received ${result.tokenReceivedFloat} tokens`);API Reference
OneTrade
Main entry point that orchestrates adapters and executors.
const onetrade = new OneTrade({
connection: Connection,
adapters: ProtocolAdapter[],
executors: Executor[],
});quote(intent)
Get a price quote without executing a trade.
const quote = await onetrade.quote({
protocol: "bonkfun",
side: "buy",
mint: new PublicKey("TOKEN_MINT"),
amountType: "exactIn",
amount: 100_000_000n, // 0.1 SOL
slippagePercent: 5,
signer, // Required but not used for signing
});
console.log(`Input: ${quote.expectedInFloat} SOL`);
console.log(`Output: ${quote.expectedOutFloat} tokens`);trade(intent, options)
Execute a trade and return the result.
const result = await onetrade.trade(intent, {
executor: "jito" | "rpc",
confirmation: "processed" | "confirmed" | "finalized",
overrideTipLamports: number, // Optional: override Jito tip for this trade
});TradeIntent
Describes what trade to execute.
interface TradeIntent {
protocol: "pumpfun" | "pumpswap" | "bonkfun" | "bonkers" | "moonshot" | "moonit" | "daosfun" | "jupiterstudio" | "raydiumlaunchlab" | "bagsfm" | "meteoravirtualcurve" | "raydiumcpmm";
side: "buy" | "sell";
mint?: PublicKey; // Token mint (required for pumpfun, bonkfun)
pair?: PublicKey; // Pool address (optional for pumpswap)
amount: bigint; // Amount in lamports/base units
amountType: "exactIn"; // Slippage direction
slippagePercent: number;
signer: Keypair;
buildOptions?: {
preferV0?: boolean;
forceLegacy?: boolean;
computeOverride?: { units?: number; microLamports?: number };
};
}QuoteResult
Returned from quote() with expected input/output amounts.
interface QuoteResult {
expectedIn: bigint;
expectedInFloat: number;
expectedOut: bigint;
expectedOutFloat: number;
}TradeResult
Returned from successful trades with both raw and float values.
interface TradeResult {
signature: string;
slot: number;
solSpent: bigint;
solSpentFloat: number;
solReceived: bigint;
solReceivedFloat: number;
tokenSpent: bigint;
tokenSpentFloat: number;
tokenReceived: bigint;
tokenReceivedFloat: number;
}Executors
JitoExecutor
MEV-protected transaction submission via Jito block engine.
const jitoExecutor = new JitoExecutor({
connection,
config: {
region: "mainnet" | "ny" | "amsterdam" | "frankfurt" | "tokyo",
authKeypair: Keypair,
tipLamports: number, // Default: 1_000_000
},
});Overriding Jito Tip Per-Trade
You can override the default tip amount for individual trades using overrideTipLamports:
const result = await onetrade.trade(
{
protocol: "pumpfun",
side: "buy",
mint: new PublicKey("TOKEN_MINT_ADDRESS"),
amountType: "exactIn",
amount: 100_000_000n,
slippagePercent: 5,
signer,
},
{
executor: "jito",
overrideTipLamports: 2_000_000, // Use 0.002 SOL tip instead of default
}
);RpcExecutor
Standard RPC transaction submission with automatic retry.
const rpcExecutor = new RpcExecutor({
connection,
config: {
commitment: "confirmed",
},
});Examples
Buy on Pump.fun Bonding Curve
const result = await onetrade.trade(
{
protocol: "pumpfun",
side: "buy",
mint: new PublicKey("TOKEN_MINT_ADDRESS"),
amountType: "exactIn",
amount: 100_000_000n, // 0.1 SOL
slippagePercent: 5,
signer,
},
{ executor: "jito" }
);Sell on Pump.fun Bonding Curve
const result = await onetrade.trade(
{
protocol: "pumpfun",
side: "sell",
mint: new PublicKey("TOKEN_MINT_ADDRESS"),
amountType: "exactIn",
amount: 1_000_000_000n, // Token amount in base units
slippagePercent: 5,
signer,
},
{ executor: "jito" }
);Buy on PumpSwap AMM
const result = await onetrade.trade(
{
protocol: "pumpswap",
side: "buy",
pair: new PublicKey("POOL_ADDRESS"),
amountType: "exactIn",
amount: 100_000_000n,
slippagePercent: 5,
signer,
},
{ executor: "jito" }
);Buy on Bonk.fun Launchpad
import { RaydiumLaunchLabAdapter } from "onetrade-sdk";
const onetrade = new OneTrade({
connection,
adapters: [new RaydiumLaunchLabAdapter(connection, "bonkfun")],
executors: [jitoExecutor],
});
const result = await onetrade.trade(
{
protocol: "bonkfun",
side: "buy",
mint: new PublicKey("TOKEN_MINT_ADDRESS"),
amountType: "exactIn",
amount: 100_000_000n, // 0.1 SOL
slippagePercent: 5,
signer,
},
{ executor: "jito" }
);Sell on Bonk.fun Launchpad
const result = await onetrade.trade(
{
protocol: "bonkfun",
side: "sell",
mint: new PublicKey("TOKEN_MINT_ADDRESS"),
amountType: "exactIn",
amount: tokenBalance, // Token amount in base units
slippagePercent: 5,
signer,
},
{ executor: "jito" }
);Buy on Bonkers Launchpad
import { RaydiumLaunchLabAdapter } from "onetrade-sdk";
const onetrade = new OneTrade({
connection,
adapters: [new RaydiumLaunchLabAdapter(connection, "bonkers")],
executors: [jitoExecutor],
});
const result = await onetrade.trade(
{
protocol: "bonkers",
side: "buy",
mint: new PublicKey("TOKEN_MINT_ADDRESS"),
amountType: "exactIn",
amount: 100_000_000n, // 0.1 SOL
slippagePercent: 5,
signer,
},
{ executor: "jito" }
);Buy on Moonshot Launchpad
import { MeteoraDBCAdapter } from "onetrade-sdk";
const onetrade = new OneTrade({
connection,
adapters: [new MeteoraDBCAdapter(connection, "moonshot")],
executors: [jitoExecutor],
});
const result = await onetrade.trade(
{
protocol: "moonshot",
side: "buy",
mint: new PublicKey("TOKEN_MINT_ADDRESS"),
amountType: "exactIn",
amount: 100_000_000n, // 0.1 SOL
slippagePercent: 5,
signer,
},
{ executor: "jito" }
);Buy on Moonit
import { MoonitAdapter } from "onetrade-sdk";
const onetrade = new OneTrade({
connection,
adapters: [new MoonitAdapter(rpcUrl)],
executors: [jitoExecutor],
});
const result = await onetrade.trade(
{
protocol: "moonit",
side: "buy",
mint: new PublicKey("TOKEN_MINT_ADDRESS"),
amountType: "exactIn",
amount: 100_000n, // 0.0001 SOL
slippagePercent: 5,
signer,
},
{ executor: "jito" }
);Sell on Moonit (Full Balance)
import { MoonitAdapter, getTokenBalance } from "onetrade-sdk";
const onetrade = new OneTrade({
connection,
adapters: [new MoonitAdapter(rpcUrl)],
executors: [jitoExecutor],
});
// Get full token balance
const tokenBalance = await getTokenBalance(connection, signer.publicKey, mint);
const result = await onetrade.trade(
{
protocol: "moonit",
side: "sell",
mint: new PublicKey("TOKEN_MINT_ADDRESS"),
amountType: "exactIn",
amount: tokenBalance,
slippagePercent: 5,
signer,
},
{ executor: "jito" }
);Buy on DAOs.fun
import { MeteoraDBCAdapter } from "onetrade-sdk";
const onetrade = new OneTrade({
connection,
adapters: [new MeteoraDBCAdapter(connection, "daosfun")],
executors: [jitoExecutor],
});
const result = await onetrade.trade(
{
protocol: "daosfun",
side: "buy",
mint: new PublicKey("TOKEN_MINT_ADDRESS"),
amountType: "exactIn",
amount: 1_000_000n, // 0.001 SOL
slippagePercent: 5,
signer,
},
{ executor: "jito" }
);Sell on DAOs.fun (Full Balance)
import { MeteoraDBCAdapter, getTokenBalance } from "onetrade-sdk";
const onetrade = new OneTrade({
connection,
adapters: [new MeteoraDBCAdapter(connection, "daosfun")],
executors: [jitoExecutor],
});
// Get full token balance
const tokenBalance = await getTokenBalance(connection, signer.publicKey, mint);
const result = await onetrade.trade(
{
protocol: "daosfun",
side: "sell",
mint: new PublicKey("TOKEN_MINT_ADDRESS"),
amountType: "exactIn",
amount: tokenBalance,
slippagePercent: 5,
signer,
},
{ executor: "jito" }
);Buy on Jupiter Studio
import { MeteoraDBCAdapter } from "onetrade-sdk";
const onetrade = new OneTrade({
connection,
adapters: [new MeteoraDBCAdapter(connection, "jupiterstudio")],
executors: [jitoExecutor],
});
const result = await onetrade.trade(
{
protocol: "jupiterstudio",
side: "buy",
mint: new PublicKey("TOKEN_MINT_ADDRESS"),
amountType: "exactIn",
amount: 1_000n, // 0.001 USDC (6 decimals)
slippagePercent: 5,
signer,
},
{ executor: "jito" }
);Sell on Jupiter Studio (Full Balance)
import { MeteoraDBCAdapter, getTokenBalance } from "onetrade-sdk";
const onetrade = new OneTrade({
connection,
adapters: [new MeteoraDBCAdapter(connection, "jupiterstudio")],
executors: [jitoExecutor],
});
// Get full token balance
const tokenBalance = await getTokenBalance(connection, signer.publicKey, mint);
const result = await onetrade.trade(
{
protocol: "jupiterstudio",
side: "sell",
mint: new PublicKey("TOKEN_MINT_ADDRESS"),
amountType: "exactIn",
amount: tokenBalance,
slippagePercent: 5,
signer,
},
{ executor: "jito" }
);Buy on Raydium LaunchLab (Generic)
import { RaydiumLaunchLabAdapter } from "onetrade-sdk";
const onetrade = new OneTrade({
connection,
adapters: [new RaydiumLaunchLabAdapter(connection, "raydiumlaunchlab")],
executors: [jitoExecutor],
});
const result = await onetrade.trade(
{
protocol: "raydiumlaunchlab",
side: "buy",
mint: new PublicKey("TOKEN_MINT_ADDRESS"),
amountType: "exactIn",
amount: 10_000n, // 0.00001 SOL
slippagePercent: 5,
signer,
},
{ executor: "jito" }
);Sell on Raydium LaunchLab (Full Balance)
import { RaydiumLaunchLabAdapter, getTokenBalance } from "onetrade-sdk";
const onetrade = new OneTrade({
connection,
adapters: [new RaydiumLaunchLabAdapter(connection, "raydiumlaunchlab")],
executors: [jitoExecutor],
});
// Get full token balance
const tokenBalance = await getTokenBalance(connection, signer.publicKey, mint);
const result = await onetrade.trade(
{
protocol: "raydiumlaunchlab",
side: "sell",
mint: new PublicKey("TOKEN_MINT_ADDRESS"),
amountType: "exactIn",
amount: tokenBalance,
slippagePercent: 5,
signer,
},
{ executor: "jito" }
);Architecture
TradeIntent → Adapter.buildTradePlan() → Executor.execute() → TradeResultCore Components
| Component | Description |
|-----------|-------------|
| OneTrade | Main orchestrator that routes trades to adapters and executors |
| Adapters | Convert TradeIntent into TxPlan with protocol-specific instructions |
| Executors | Submit transactions to Solana (Jito bundles or standard RPC) |
| Outcome Decoder | Parse transaction logs to extract trade results |
Project Structure
src/
├── core/ # OneTrade class, types, errors, slippage utils
├── adapters/ # Protocol implementations (pumpfun, pumpswap, raydium-launchlab, meteora-dbc, moonit)
├── executor/ # Transaction submission (Jito, RPC)
├── outcome/ # Transaction log parsing
├── builder/ # V0/Legacy transaction construction
└── read/ # Token info, balances, ATA utilitiesError Handling
The SDK provides specific error codes via OneTradeError:
| Code | Description |
|------|-------------|
| UNSUPPORTED_MODE | Protocol doesn't support requested trade type |
| PROTOCOL_UNAVAILABLE | Token/pool not found or unavailable |
| INSUFFICIENT_FUNDS | User lacks required balance |
| SLIPPAGE_EXCEEDED | Trade output below minimum |
| BLOCKHASH_EXPIRED | Transaction invalidated |
| PROGRAM_ERROR | On-chain program error |
| OUTCOME_DECODE_FAILED | Unable to parse transaction results |
import { OneTradeError, OneTradeErrorCode } from "onetrade-sdk";
try {
await onetrade.trade(intent, options);
} catch (err) {
if (err instanceof OneTradeError) {
if (err.code === OneTradeErrorCode.SLIPPAGE_EXCEEDED) {
// Handle slippage
}
}
}Adding New Adapters
- Create adapter in
src/adapters/<protocol>/adapter.ts - Implement
ProtocolAdapterinterface - Add protocol ID to
ProtocolIdtype insrc/core/types.ts - Export from
src/index.ts
interface ProtocolAdapter {
readonly protocol: ProtocolId;
readonly capabilities: AdapterCapabilities;
readonly eventSpec?: EventSpec;
buildTradePlan(intent: TradeIntent, context: AdapterContext): Promise<TxPlan>;
quote?(intent: TradeIntent, context: AdapterContext): Promise<Quote>;
}Environment Variables
RPC_URL=https://api.mainnet-beta.solana.com
PRIVATE_KEY=<base58-encoded-keypair>
JITO_AUTH_PRIVATE_KEY=<base58-encoded-keypair>Development
# Build
pnpm build
# Clean
pnpm clean
# Run examples
pnpm example:pumpfun:buy
pnpm example:pumpfun:sell
pnpm example:pumpfun:quote
pnpm example:pumpswap:buy
pnpm example:pumpswap:sell
pnpm example:pumpswap:quote
pnpm example:bonkfun:buy
pnpm example:bonkfun:sell
pnpm example:bonkfun:quote
pnpm example:bonkers:buy
pnpm example:bonkers:sell
pnpm example:bonkers:quote
pnpm example:moonshot:buy
pnpm example:moonshot:sell
pnpm example:moonshot:quote
pnpm example:moonit:buy
pnpm example:moonit:sell
pnpm example:moonit:quote
pnpm example:daosfun:buy
pnpm example:daosfun:sell
pnpm example:daosfun:quote
pnpm example:jupiterstudio:buy
pnpm example:jupiterstudio:sell
pnpm example:jupiterstudio:quote
pnpm example:raydiumlaunchlab:buy
pnpm example:raydiumlaunchlab:sell
pnpm example:raydiumlaunchlab:quote
pnpm example:bagsfm:buy
pnpm example:bagsfm:sell
pnpm example:bagsfm:quote
pnpm example:meteoravirtualcurve:buy
pnpm example:meteoravirtualcurve:sell
pnpm example:meteoravirtualcurve:quote
pnpm example:raydiumcpmm:buy
pnpm example:raydiumcpmm:sell
pnpm example:raydiumcpmm:quoteLicense
MIT
