Build Transaction
Solana API for building swap transactions with DEX routing, gasless mode, privy wallets, and custom fees. Returns base64 unsigned transactions.
Build an unsigned swap transaction ready for signing and submission. The API returns a base64-encoded transaction containing all necessary instructions—token transfers, DEX calls, and fee handling—in a single atomic transaction.
How It Works
The build transaction endpoint:
- Finds the best route across supported DEXs
- Calculates fee from swap amount (not separate wallet balance)
- Creates all required accounts (ATAs if needed)
- Builds DEX swap instructions for the optimal pool
- Adds fee transfer instruction (direct token transfer, no temp accounts)
- Returns a base64 transaction ready for signing
You receive a complete, optimized transaction that just needs a signature.
Note: Your application signs the transaction with the user's wallet and submits it to the Solana network. Vybe never touches private keys—we only build the transaction; signing and submission happen entirely on your side
Smart Fee Handling
When you set a fee, Vybe deducts it from the swap tokens directly—not from a separate wallet balance. This means:
- No "Insufficient SOL for fee" errors when swapping SOL
- No temporary fee accounts (saves at least ~0.004 SOL in rent)
- Fee is extracted atomically within the same transaction
See Slippage & Fees for full details on fee priority logic.
Endpoint
POST /trading/swap
Request Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
wallet | string | ✅ | User's wallet public key | |
amount | number | ✅ | Amount to swap (UI units, e.g., 0.1 SOL) | |
inputMint | string | ✅ | Input token mint address | |
outputMint | string | ✅ | Output token mint address | |
router | string | ❌ | "vybe" | Router mode: "vybe", "titan", "jupiter" |
slippage | number | ❌ | 5 | Slippage tolerance (percentage, e.g., 2 for 2%) |
fee | number | ❌ | 0 | Service fee percentage (e.g., 1 for 1%) |
simulate | boolean | ❌ | false | Simulate only, don't return transaction |
gasless | boolean | ❌ | false | Use Vybe as fee payer |
protocol | string | ❌ | Force specific protocol (e.g., "PUMPFUN") | |
pool | string | ❌ | Force specific pool address | |
vybeOnly | boolean | ❌ | false | No fallback to aggregators |
Example Request
curl -X POST "https://api.vybenetwork.com/trading/swap" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"wallet": "7Tar8QZTrRPwoGY5Ke9Vfwf6CmpBfekrNofERxgReza",
"amount": 0.1,
"inputMint": "So11111111111111111111111111111111111111112",
"outputMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"router": "vybe",
"slippage": 1,
"fee": 0.5
}'Example Response
{
"transaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAHDg...",
"inputAmount": 100000000,
"inputToken": "So11111111111111111111111111111111111111112",
"outputToken": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"inputDecimals": 9,
"outputDecimals": 6,
"swapFee": 500000,
"protocol": "RAYDIUM_CLMM",
"poolAddress": "8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj",
"quote": {
"inAmount": "100000000",
"outAmount": "18523456",
"priceImpactPct": 0.01
}
}Response Fields
| Field | Description |
|---|---|
transaction | Base64-encoded unsigned transaction |
inputAmount | Input amount in base units |
inputToken | Input token mint address |
outputToken | Output token mint address |
inputDecimals | Input token decimal places |
outputDecimals | Output token decimal places |
swapFee | Fee amount in base units |
protocol | DEX protocol used |
poolAddress | Pool address used for swap |
quote | Quote details (amounts, price impact) |
Complete Flow: Sign and Submit
Here's how to execute a swap end-to-end:
Using @solana/web3.js
import { Connection, Transaction, Keypair } from '@solana/web3.js';
async function executeSwap(wallet, inputMint, outputMint, amount) {
// Step 1: Build the transaction
const response = await fetch('https://api.vybenetwork.com/trading/swap', {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
wallet: wallet.publicKey.toString(),
amount,
inputMint,
outputMint,
router: 'vybe',
slippage: 2
})
});
const { transaction: txBase64, quote } = await response.json();
// Step 2: Deserialize the transaction
const transaction = Transaction.from(Buffer.from(txBase64, 'base64'));
// Step 3: Sign with wallet
transaction.sign(wallet);
// Step 4: Submit to network
const connection = new Connection('https://api.mainnet-beta.solana.com');
const signature = await connection.sendRawTransaction(
transaction.serialize(),
{ skipPreflight: false }
);
// Step 5: Confirm
await connection.confirmTransaction(signature, 'confirmed');
return {
signature,
expectedOutput: quote.outAmount
};
}Using Wallet Adapter (React)
import { useWallet, useConnection } from '@solana/wallet-adapter-react';
import { Transaction } from '@solana/web3.js';
function SwapButton({ inputMint, outputMint, amount }) {
const { publicKey, signTransaction } = useWallet();
const { connection } = useConnection();
const [loading, setLoading] = useState(false);
async function handleSwap() {
if (!publicKey || !signTransaction) return;
setLoading(true);
try {
// Build transaction
const response = await fetch('https://api.vybenetwork.com/trading/swap', {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
wallet: publicKey.toString(),
amount,
inputMint,
outputMint,
router: 'vybe',
slippage: 2
})
});
const { transaction: txBase64 } = await response.json();
// Deserialize
const transaction = Transaction.from(Buffer.from(txBase64, 'base64'));
// Sign with wallet adapter
const signed = await signTransaction(transaction);
// Submit
const signature = await connection.sendRawTransaction(signed.serialize());
await connection.confirmTransaction(signature, 'confirmed');
console.log('Swap successful:', signature);
} catch (error) {
console.error('Swap failed:', error);
}
setLoading(false);
}
return (
<button onClick={handleSwap} disabled={loading}>
{loading ? 'Swapping...' : 'Swap'}
</button>
);
}Router Options
| Router | Behavior | Use When |
|---|---|---|
"vybe" | Direct DEX calls, falls back to Titan/Jupiter if needed | Maximum efficiency |
"titan" | Uses Titan aggregator | Wide token coverage |
"jupiter" | Uses Jupiter aggregator | Maximum coverage |
Force Direct Integration Only
{
"router": "vybe",
"vybeOnly": true
}This prevents any fallback to aggregators. If Vybe Router doesn't support the token pair, the request will fail.
Simulation Mode
Test swaps without creating a transaction:
{
"wallet": "...",
"amount": 1,
"inputMint": "...",
"outputMint": "...",
"simulate": true
}Returns quote and route information without the transaction, useful for testing and price discovery.
Error Handling
| Status | Error | Cause | Solution |
|---|---|---|---|
| 400 | Missing required parameters | Required fields not provided | Include all required fields |
| 400 | Invalid wallet format | Wallet is not a valid public key | Check wallet address |
| 422 | No swap route found | No liquidity for this pair | Try different router or check token |
| 422 | Insufficient balance | Wallet doesn't have enough tokens | Check balance before swap |
| 422 | Slippage exceeded | Price moved too much | Increase slippage tolerance |
Robust Error Handling
async function buildSwapWithRetry(params, maxRetries = 2) {
for (let i = 0; i <= maxRetries; i++) {
try {
const response = await fetch('https://api.vybenetwork.com/trading/swap', {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
});
if (!response.ok) {
const error = await response.json();
// Retry with higher slippage on slippage errors
if (error.message?.includes('Slippage') && i < maxRetries) {
params.slippage = (params.slippage || 2) * 2;
continue;
}
throw new Error(error.message || 'Swap failed');
}
return response.json();
} catch (error) {
if (i === maxRetries) throw error;
}
}
}Next Steps
- Supported Protocols - Force specific DEXs
- Slippage & Fees - Configure slippage and understand fees
- Gasless Mode - Execute without SOL for gas
Updated 10 days ago