A high-performance, async-first Python SDK for seamless interaction with the Jupiter Ultra API, powered by curl_cffi
for maximum speed and flexibility.
With Ultra API, you don't need to manage or connect to any RPC endpoints, or deal with complex configurations. Everything from getting quotes to transaction execution happens directly through a powerful API.
Or as we like to say around here: "RPCs are for NPCs."
- Features
- Installation
- Quick Start
- Configuration
- API Reference
- Usage Examples
- Best Practices
- Advanced Usage
- Error Handling
- Contributing
- Resources
- 🚀 High Performance: Built on
curl_cffifor blazing-fast HTTP requests - 🔄 Async/Sync Support: Both asynchronous and synchronous clients available
- 🛡️ Token Safety: Built-in shield API for token security warnings
- 💰 Balance Checking: Easy balance retrieval for any Solana address
- 🔧 Advanced Configuration: Support for proxies, custom DNS, and more
- 📦 Type Safety: Full type hints with Pydantic models
- 🎯 Zero Configuration: Works out of the box with minimal setup
install uv
uv add pyjupiter- Python 3.9 or higher
- A Solana wallet private key (for transaction signing)
import asyncio
from pyjupiter.clients.ultra_api_client import AsyncUltraApiClient
from pyjupiter.models.ultra_api.ultra_order_request_model import UltraOrderRequest
async def main():
# Initialize the async client
client = AsyncUltraApiClient()
# Create a swap order
order_request = UltraOrderRequest(
input_mint="So11111111111111111111111111111111111111112", # WSOL
output_mint="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", # USDC
amount=10000000, # 0.01 WSOL
taker=await client.get_public_key(),
)
try:
# Execute the swap
response = await client.order_and_execute(order_request)
print(f"Transaction: https://solscan.io/tx/{response['signature']}")
finally:
await client.close()
asyncio.run(main())from pyjupiter.clients.ultra_api_client import UltraApiClient
from pyjupiter.models.ultra_api.ultra_order_request_model import UltraOrderRequest
# Initialize the sync client
client = UltraApiClient()
# Create and execute a swap
order_request = UltraOrderRequest(
input_mint="So11111111111111111111111111111111111111112", # WSOL
output_mint="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", # USDC
amount=10000000, # 0.01 WSOL
taker=client.get_public_key(),
)
response = client.order_and_execute(order_request)
print(f"Transaction: https://solscan.io/tx/{response['signature']}")
client.close()Set up your private key as an environment variable:
# Base58 format (standard Solana format)
export PRIVATE_KEY=your_base58_private_key_here
# OR as a uint8 array
export PRIVATE_KEY=[10,229,131,132,213,96,74,22,...]from pyjupiter.clients.ultra_api_client import AsyncUltraApiClient
# With API key (for enhanced access)
client = AsyncUltraApiClient(
api_key="YOUR_API_KEY", # Get from https://portal.jup.ag/onboard
private_key_env_var="CUSTOM_PRIVATE_KEY" # Custom env var name
)
# With custom client configuration
client = AsyncUltraApiClient(
client_kwargs={
"timeout": 30, # 30 seconds timeout
"verify": True, # SSL verification
}
)The main client classes for interacting with the Jupiter Ultra API.
Get a swap order from the Jupiter Ultra API.
Parameters:
request: AnUltraOrderRequestobject containing:input_mint(str): Input token mint addressoutput_mint(str): Output token mint addressamount(int): Amount in smallest unit (e.g., lamports for SOL)taker(str, optional): Taker's public keyreferral_account(str, optional): Referral account addressreferral_fee(int, optional): Referral fee in basis points
Returns: Dict containing order details including requestId and transaction
Execute a previously created order.
Parameters:
request: AnUltraExecuteRequestobject containing:request_id(str): The request ID from the ordersigned_transaction(str): Base64-encoded signed transaction
Returns: Dict containing execution result including signature and status
Create and execute an order in a single call.
Parameters:
request: Same asorder()method
Returns: Dict containing execution result including signature and status
Get token balances for a Solana address.
Parameters:
address(str): Solana public key address
Returns: Dict mapping token symbols to balance details:
{
"SOL": {
"amount": "100000000",
"uiAmount": 0.1,
"slot": 123456,
"isFrozen": False
}
}Check tokens for safety warnings.
Parameters:
mints(list[str]): List of token mint addresses to check
Returns: Dict containing warnings for each mint:
{
"warnings": {
"mint_address": [
{
"type": "warning_type",
"message": "Warning description"
}
]
}
}Pydantic model for creating swap orders.
UltraOrderRequest(
input_mint="So11111111111111111111111111111111111111112",
output_mint="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
amount=10000000,
taker="your_public_key",
referral_account="optional_referral_address",
referral_fee=50 # 0.5% in basis points
)Pydantic model for executing orders.
UltraExecuteRequest(
request_id="order_request_id",
signed_transaction="base64_encoded_signed_transaction"
)import asyncio
from pyjupiter.clients.ultra_api_client import AsyncUltraApiClient
async def check_balances():
client = AsyncUltraApiClient()
# Get your wallet address
address = await client.get_public_key()
# Fetch balances
balances = await client.balances(address)
for token, details in balances.items():
print(f"{token}: {details['uiAmount']} (frozen: {details['isFrozen']})")
await client.close()
asyncio.run(check_balances())import asyncio
from pyjupiter.clients.ultra_api_client import AsyncUltraApiClient
async def check_token_safety():
client = AsyncUltraApiClient()
# Popular tokens to check
mints = [
"So11111111111111111111111111111111111111112", # WSOL
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", # USDC
"DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263", # BONK
]
shield_response = await client.shield(mints)
for mint, warnings in shield_response.get("warnings", {}).items():
if warnings:
print(f"⚠️ {mint} has warnings:")
for warning in warnings:
print(f" - {warning['type']}: {warning['message']}")
else:
print(f"✅ {mint} appears safe")
await client.close()
asyncio.run(check_token_safety())import asyncio
from pyjupiter.clients.ultra_api_client import AsyncUltraApiClient
async def concurrent_operations():
client = AsyncUltraApiClient()
# Define multiple tokens to check
tokens = [
"So11111111111111111111111111111111111111112",
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
]
# Create tasks for concurrent execution
tasks = []
for token in tokens:
task = client.shield([token])
tasks.append(task)
# Execute all requests concurrently
results = await asyncio.gather(*tasks)
# Process results
for token, result in zip(tokens, results):
print(f"Token {token}: {result}")
await client.close()
asyncio.run(concurrent_operations())# Using try/finally
client = AsyncUltraApiClient()
try:
# Your code here
pass
finally:
await client.close()
# Or using async context manager (if implemented)
async with AsyncUltraApiClient() as client:
# Your code here
passtry:
response = await client.order_and_execute(order_request)
if response.get("status") == "Failed":
print(f"Transaction failed: {response.get('error')}")
else:
print(f"Success: {response['signature']}")
except Exception as e:
print(f"Error occurred: {e}")import asyncio
# Use semaphore to limit concurrent requests
semaphore = asyncio.Semaphore(5) # Max 5 concurrent requests
async def rate_limited_request(client, mint):
async with semaphore:
return await client.shield([mint])import asyncio
from typing import Optional
async def retry_request(func, max_retries=3, delay=1.0):
for attempt in range(max_retries):
try:
return await func()
except Exception as e:
if attempt == max_retries - 1:
raise
await asyncio.sleep(delay * (attempt + 1))# Always work with the smallest unit (lamports for SOL)
sol_amount = 0.01 # SOL
lamports = int(sol_amount * 10**9) # Convert to lamports
# For other tokens, check their decimals
usdc_amount = 10.0 # USDC
usdc_smallest_unit = int(usdc_amount * 10**6) # USDC has 6 decimals# SOCKS5 proxy
proxies = {"https": "socks5://user:pass@host:port"}
client = AsyncUltraApiClient(client_kwargs={"proxies": proxies})
# HTTP proxy
proxies = {
"http": "http://user:pass@proxy.example.com:8080",
"https": "http://user:pass@proxy.example.com:8080",
}
client = AsyncUltraApiClient(client_kwargs={"proxies": proxies})# Force specific DNS resolution
client = AsyncUltraApiClient(
client_kwargs={
"resolve": ["api.jup.ag:443:1.2.3.4"],
"dns_servers": ["1.1.1.1", "1.0.0.1"],
}
)# Default client
client = AsyncUltraApiClient()
# With custom timeout
client = AsyncUltraApiClient(
client_kwargs={
"timeout": 60, # 60 seconds timeout
}
)
# With custom headers
client = AsyncUltraApiClient(
client_kwargs={
"headers": {
"Accept-Language": "en-US,en;q=0.9",
}
}
)The SDK may raise various exceptions:
try:
response = await client.order_and_execute(order_request)
except ValueError as e:
# Invalid private key format
print(f"Configuration error: {e}")
except requests.HTTPError as e:
# HTTP errors (4xx, 5xx)
print(f"API error: {e}")
except Exception as e:
# Other errors
print(f"Unexpected error: {e}")response = await client.order_and_execute(order_request)
if response.get("status") == "Failed":
error_code = response.get("code")
error_message = response.get("error")
if error_code == "INSUFFICIENT_BALANCE":
print("Not enough balance for the swap")
elif error_code == "SLIPPAGE_EXCEEDED":
print("Slippage tolerance exceeded")
else:
print(f"Transaction failed: {error_message}")Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
# Clone the repository
git clone https://github.com/solanab/pyjupiter.git
cd pyjupiter
# Install development dependencies
uv sync
# Run tests
just ta
# Run linters
just l
just f- Ultra API Documentation
- Jupiter Portal - Get your API key
- Discord Community
- GitHub Repository
This project is licensed under the MIT License - see the LICENSE file for details.