Skip to main content
Part of the How to land transactions on Solana guide.
TLDR:
  • Jupiter offers a quick way to swap tokens on Solana but lacks a Python SDK, so we query Jupiter’s public API for quotes and transaction data.
  • We calculate our priority fee by fetching recent block data via getRecentPrioritizationFees, then derive the median fee and multiply it by a user-defined factor.
  • Adding this priority fee to the raw Jupiter transaction data (plus the base fee of 5000 lamports) helps ensure faster block inclusion under congestion.
  • The entire flow uses both Jupiter endpoints (quote + swap) and a private Solana RPC (e.g., Chainstack) for the final transaction broadcast, giving you more control over performance and reliability.
Jupiter retired the old quote-api.jup.ag/v6 endpoints on October 1, 2025. This guide uses the current Swap API at https://api.jup.ag/swap/v1. The keyless https://lite-api.jup.ag/swap/v1 works for low request rates; api.jup.ag takes an X-API-Key header for higher tiers (get a key at portal.jup.ag). Jupiter also offers a newer consolidated Swap API v2; the v1 flow below is verified end to end.

Main article

With its cumulative volume in USD billions, Jupiter is one of the top DEX aggregators on Solana. In this tutorial, we are going to have a look at how add our own prioritization fees to swap for a token pair through a Jupiter aggregator route. As Jupiter does not have a Python SDK at the time of this tutorial, it’s more fun doing this in Python. For JavaScript, check out the Jupiter developer docs.

Transaction fees on Solana

The topic of transactions fees on Solana is both a nascent development and its own can of worms at the same time, so we are not going to do a deep dive into this. Here’s however what you need to know in a succinct form for this tutorial:
  • Base fee — fixed 5000 lamports (0.000005 SOL) per transaction signature, which 99% of the time means 5000 lamports per transaction
  • Priority fee — a non-fixed amount that you can include in your transaction on top of the 5000 lamports base fee to get ahead of others in the queue for the block inclusion of the current leader.
So in theory — the higher the priority fee, the more chances you have to skip ahead and become a part of the state of the chain than the others you are racing against. Let’s implement adding a proper priority fee to our transaction based on an interaction with the Jupiter aggregator.

Run Solana mainnet and devnet nodes on Chainstack

Start for free and get your app to production levels immediately. No credit card required. You can sign up with your GitHub, X, Google, or Microsoft account.
Get yourself a Chainstack Solana node.

Overview

Here’s how it’s going to work:
  1. Get a token pair price quote from the Jupiter API.
  2. Get the priority fees data from the recent 150 blocks with the getRecentPrioritizationFees call from a Chainstack Solana node.
  3. Calculate the priority fee to include with your transaction.
  4. Submit the transaction through the Chainstack Solana node:
    1. Transaction data (token pair exchange rate, liquidity pool) from the Jupiter API quote
    2. Priority fee based on the raw chain data obtained through the Chainstack Solana node

Implementation

The flow is: estimate a priority fee from recent on-chain data, get a quote from Jupiter, build the swap transaction with that fee, then sign and send it through your own Solana node. Jupiter doesn’t have an official Python SDK, so we call its REST API directly and sign with solders. Install the dependencies:
pip install requests solders solana
The complete script:
jupiter_swap.py
import base64
import statistics

import requests
from solders.keypair import Keypair
from solders.transaction import VersionedTransaction
from solana.rpc.api import Client
from solana.rpc.types import TxOpts

# Your Chainstack Solana node and wallet
RPC_ENDPOINT = "YOUR_CHAINSTACK_SOLANA_NODE"
PRIVATE_KEY = "YOUR_PRIVATE_KEY"  # base58-encoded

# Jupiter Swap API. lite-api.jup.ag is keyless (low rate); api.jup.ag takes an
# X-API-Key header for higher tiers — get a key at https://portal.jup.ag
JUPITER = "https://api.jup.ag/swap/v1"

INPUT_MINT = "So11111111111111111111111111111111111111112"   # SOL
OUTPUT_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"  # USDC
AMOUNT = 1_000_000          # 0.001 SOL, in lamports
SLIPPAGE_BPS = 50           # 0.5%
PRIORITY_MULTIPLIER = 1.1   # bump over the median fee

wallet = Keypair.from_base58_string(PRIVATE_KEY)

# 1) Estimate the priority fee from recent blocks. Use the median, not the max:
#    occasional astronomical fees on-chain can drain your wallet if you chase them.
resp = requests.post(RPC_ENDPOINT, json={
    "jsonrpc": "2.0", "id": 1, "method": "getRecentPrioritizationFees",
    "params": [[INPUT_MINT]],  # account-aware: fees for the accounts your tx touches
}).json()
fees = [x["prioritizationFee"] for x in resp["result"]]
median_fee = int(statistics.median(fees)) if fees else 0
max_lamports = int(median_fee * PRIORITY_MULTIPLIER) or 1_000
print(f"Median priority fee: {median_fee} microlamports/CU")

# 2) Get a quote from Jupiter.
quote = requests.get(f"{JUPITER}/quote", params={
    "inputMint": INPUT_MINT, "outputMint": OUTPUT_MINT,
    "amount": AMOUNT, "slippageBps": SLIPPAGE_BPS,
}).json()
print(f"Quote: {AMOUNT} -> {quote['outAmount']} (out)")

# 3) Build the swap transaction with the priority fee and a dynamic compute-unit limit.
swap = requests.post(f"{JUPITER}/swap", json={
    "quoteResponse": quote,
    "userPublicKey": str(wallet.pubkey()),
    "dynamicComputeUnitLimit": True,
    "prioritizationFeeLamports": {
        "priorityLevelWithMaxLamports": {
            "maxLamports": max_lamports,
            "priorityLevel": "veryHigh",
        }
    },
}).json()

# 4) Sign the returned versioned transaction and send it through your node.
raw = VersionedTransaction.from_bytes(base64.b64decode(swap["swapTransaction"]))
signed = VersionedTransaction(raw.message, [wallet])

client = Client(RPC_ENDPOINT)
sig = client.send_raw_transaction(bytes(signed), opts=TxOpts(skip_preflight=True)).value
print(f"Sent: https://solscan.io/tx/{sig}")
A few notes on the current Jupiter API:
  • Priority fee shape. prioritizationFeeLamports.priorityLevelWithMaxLamports lets Jupiter pick a fee at the chosen priorityLevel (medium, high, or veryHigh) capped at maxLamports. Here we cap it at the median-derived value so we never overpay during a fee spike.
  • dynamicComputeUnitLimit: true makes Jupiter simulate the swap and set an accurate compute-unit limit, which both improves landing and avoids overpaying (the priority fee is compute_unit_price × compute_unit_limit).
  • Versioned transactions. Jupiter returns a base64 VersionedTransaction; sign it with solders and broadcast the raw bytes through your node.
  • Why the median. Fees over the recent window can include random astronomical outliers — basing your fee on the max can drain your wallet. The median (optionally bumped by PRIORITY_MULTIPLIER) is a safer baseline. Tune it for your needs.
The companion repository jupiter-swaps-priority-fees-python has the full project. The base fee on Solana is a fixed 5000 lamports per signature; the priority fee above is added on top.

Conclusion

Solana is a very fun and extremely lively ecosystem, so have fun building, keep and eye on the all changes and how the fee market develops — this can give you an edge. And use Chainstack, of course.

Ake

Ake Director of Developer Experience @ Chainstack
Talk to me all things Web3
20 years in technology | 8+ years in Web3 full time years experience
Last modified on July 2, 2026