solanab-jup-python-sdk 2.0.3__tar.gz → 2.0.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/.github/workflows/ci.yml +6 -1
  2. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/.gitignore +9 -5
  3. solanab_jup_python_sdk-2.0.6/.pre-commit-config.yaml +15 -0
  4. solanab_jup_python_sdk-2.0.6/PKG-INFO +592 -0
  5. solanab_jup_python_sdk-2.0.6/README.md +554 -0
  6. solanab_jup_python_sdk-2.0.6/check_code.sh +13 -0
  7. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/jup_python_sdk/clients/jupiter_client.py +102 -2
  8. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/jup_python_sdk/models/common/dex_enum.py +13 -0
  9. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/jup_python_sdk/models/ultra_api/ultra_execute_request_model.py +14 -0
  10. solanab_jup_python_sdk-2.0.6/jup_python_sdk/models/ultra_api/ultra_order_request_model.py +38 -0
  11. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/pyproject.toml +21 -30
  12. solanab_jup_python_sdk-2.0.6/tests/test_client_functionality.py +149 -0
  13. solanab_jup_python_sdk-2.0.6/tests/test_ultra_balances.py +58 -0
  14. solanab_jup_python_sdk-2.0.6/tests/test_ultra_order_and_execute.py +68 -0
  15. solanab_jup_python_sdk-2.0.6/tests/test_ultra_shield.py +70 -0
  16. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/uv.lock +209 -686
  17. solanab_jup_python_sdk-2.0.3/.pre-commit-config.yaml +0 -17
  18. solanab_jup_python_sdk-2.0.3/PKG-INFO +0 -158
  19. solanab_jup_python_sdk-2.0.3/README-dev.md +0 -16
  20. solanab_jup_python_sdk-2.0.3/README-release.md +0 -30
  21. solanab_jup_python_sdk-2.0.3/README.md +0 -125
  22. solanab_jup_python_sdk-2.0.3/check_code.sh +0 -5
  23. solanab_jup_python_sdk-2.0.3/jup_python_sdk/models/ultra_api/ultra_order_request_model.py +0 -20
  24. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/.github/workflows/release.yml +0 -0
  25. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/LICENSE +0 -0
  26. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/examples/advanced/concurrent_example.py +0 -0
  27. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/examples/advanced/proxy_example.py +0 -0
  28. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/examples/balances/async_main.py +0 -0
  29. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/examples/balances/main.py +0 -0
  30. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/examples/order-and-execute/async_main.py +0 -0
  31. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/examples/order-and-execute/main.py +0 -0
  32. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/examples/shield/async_main.py +0 -0
  33. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/examples/shield/main.py +0 -0
  34. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/jup_python_sdk/__init__.py +0 -0
  35. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/jup_python_sdk/clients/__init__.py +0 -0
  36. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/jup_python_sdk/clients/ultra_api_client.py +0 -0
  37. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/jup_python_sdk/models/__init__.py +0 -0
  38. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/jup_python_sdk/models/common/__init__.py +0 -0
  39. {solanab_jup_python_sdk-2.0.3 → solanab_jup_python_sdk-2.0.6}/jup_python_sdk/models/ultra_api/__init__.py +0 -0
@@ -37,4 +37,9 @@ jobs:
37
37
  - name: Run Linting
38
38
  run: |
39
39
  uv run ruff check .
40
- uv run ruff format --check .
40
+ uv run ruff format --check .
41
+
42
+ - name: Security Scanning
43
+ run: |
44
+ uv run bandit -r jup_python_sdk -ll
45
+ uv run pip-audit
@@ -66,12 +66,16 @@ docs/_build/
66
66
  .env.*
67
67
 
68
68
  # UV specific
69
- # uv.lock # Keep lock file for reproducible builds
70
69
  .python-version
71
70
 
72
- # Temporary test files
73
- test_*.py
74
- generate_*.py
75
-
76
71
  # Flake8 config
77
72
  .flake8
73
+
74
+ # ruff
75
+ .ruff_cache
76
+
77
+ # IDE
78
+ .ropeproject
79
+
80
+ # ai
81
+ .claude
@@ -0,0 +1,15 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.8.0
4
+ hooks:
5
+ # Run the linter
6
+ - id: ruff
7
+ args: [--fix]
8
+ # Run the formatter
9
+ - id: ruff-format
10
+
11
+ - repo: https://github.com/pre-commit/mirrors-mypy
12
+ rev: v1.15.0
13
+ hooks:
14
+ - id: mypy
15
+ additional_dependencies: [types-requests]
@@ -0,0 +1,592 @@
1
+ Metadata-Version: 2.4
2
+ Name: solanab-jup-python-sdk
3
+ Version: 2.0.6
4
+ Summary: High-performance sync/async Python SDK for Jupiter Exchange APIs, powered by curl_cffi.
5
+ Project-URL: homepage, https://github.com/solanab/jup-python-sdk
6
+ Project-URL: repository, https://github.com/solanab/jup-python-sdk
7
+ Author-email: Fiji <charismoutafidis@gmail.com>, solanab <whiredj@gmail.com>
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: jupiter,sdk,solana
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: >=3.9
23
+ Requires-Dist: base58>=2.1.1
24
+ Requires-Dist: curl-cffi>=0.12
25
+ Requires-Dist: pydantic>=2.11.3
26
+ Requires-Dist: solders>=0.26.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: bandit>=1.7; extra == 'dev'
29
+ Requires-Dist: mypy>=1.15.0; extra == 'dev'
30
+ Requires-Dist: pip-audit>=2.8.0; extra == 'dev'
31
+ Requires-Dist: pre-commit>=4.1.0; extra == 'dev'
32
+ Requires-Dist: pytest-asyncio>=0.23.7; extra == 'dev'
33
+ Requires-Dist: pytest-cov>=6.1.1; extra == 'dev'
34
+ Requires-Dist: pytest>=8.3.4; extra == 'dev'
35
+ Requires-Dist: python-dotenv>=1.1.0; extra == 'dev'
36
+ Requires-Dist: ruff>=0.8.0; extra == 'dev'
37
+ Description-Content-Type: text/markdown
38
+
39
+ # **Jupiter Python SDK**
40
+
41
+ [![PyPI version](https://badge.fury.io/py/solanab-jup-python-sdk.svg)](https://badge.fury.io/py/solanab-jup-python-sdk)
42
+ [![Python](https://img.shields.io/pypi/pyversions/solanab-jup-python-sdk.svg)](https://pypi.org/project/solanab-jup-python-sdk/)
43
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
44
+
45
+ A high-performance, async-first Python SDK for seamless interaction with the Jupiter Ultra API, powered by `curl_cffi` for maximum speed and flexibility.
46
+
47
+ 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.
48
+
49
+ Or as we like to say around here: **"RPCs are for NPCs."**
50
+
51
+ ## **Table of Contents**
52
+
53
+ - [Features](#features)
54
+ - [Installation](#installation)
55
+ - [Quick Start](#quick-start)
56
+ - [Configuration](#configuration)
57
+ - [API Reference](#api-reference)
58
+ - [Usage Examples](#usage-examples)
59
+ - [Best Practices](#best-practices)
60
+ - [Advanced Usage](#advanced-usage)
61
+ - [Error Handling](#error-handling)
62
+ - [Contributing](#contributing)
63
+ - [Resources](#resources)
64
+
65
+ ## **Features**
66
+
67
+ - 🚀 **High Performance**: Built on `curl_cffi` for blazing-fast HTTP requests
68
+ - 🔄 **Async/Sync Support**: Both asynchronous and synchronous clients available
69
+ - 🛡️ **Token Safety**: Built-in shield API for token security warnings
70
+ - 💰 **Balance Checking**: Easy balance retrieval for any Solana address
71
+ - 🔧 **Advanced Configuration**: Support for proxies, custom DNS, and more
72
+ - 📦 **Type Safety**: Full type hints with Pydantic models
73
+ - 🎯 **Zero Configuration**: Works out of the box with minimal setup
74
+
75
+ ## **Installation**
76
+
77
+ ```bash
78
+ pip install solanab-jup-python-sdk
79
+ ```
80
+
81
+ ### Requirements
82
+
83
+ - Python 3.9 or higher
84
+ - A Solana wallet private key (for transaction signing)
85
+
86
+ ## **Quick Start**
87
+
88
+ ### Async Example
89
+
90
+ ```python
91
+ import asyncio
92
+ from jup_python_sdk.clients.ultra_api_client import AsyncUltraApiClient
93
+ from jup_python_sdk.models.ultra_api.ultra_order_request_model import UltraOrderRequest
94
+
95
+ async def main():
96
+ # Initialize the async client
97
+ client = AsyncUltraApiClient()
98
+
99
+ # Create a swap order
100
+ order_request = UltraOrderRequest(
101
+ input_mint="So11111111111111111111111111111111111111112", # WSOL
102
+ output_mint="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", # USDC
103
+ amount=10000000, # 0.01 WSOL
104
+ taker=await client.get_public_key(),
105
+ )
106
+
107
+ try:
108
+ # Execute the swap
109
+ response = await client.order_and_execute(order_request)
110
+ print(f"Transaction: https://solscan.io/tx/{response['signature']}")
111
+ finally:
112
+ await client.close()
113
+
114
+ asyncio.run(main())
115
+ ```
116
+
117
+ ### Sync Example
118
+
119
+ ```python
120
+ from jup_python_sdk.clients.ultra_api_client import UltraApiClient
121
+ from jup_python_sdk.models.ultra_api.ultra_order_request_model import UltraOrderRequest
122
+
123
+ # Initialize the sync client
124
+ client = UltraApiClient()
125
+
126
+ # Create and execute a swap
127
+ order_request = UltraOrderRequest(
128
+ input_mint="So11111111111111111111111111111111111111112", # WSOL
129
+ output_mint="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", # USDC
130
+ amount=10000000, # 0.01 WSOL
131
+ taker=client.get_public_key(),
132
+ )
133
+
134
+ response = client.order_and_execute(order_request)
135
+ print(f"Transaction: https://solscan.io/tx/{response['signature']}")
136
+ client.close()
137
+ ```
138
+
139
+ ## **Configuration**
140
+
141
+ ### Environment Variables
142
+
143
+ Set up your private key as an environment variable:
144
+
145
+ ```bash
146
+ # Base58 format (standard Solana format)
147
+ export PRIVATE_KEY=your_base58_private_key_here
148
+
149
+ # OR as a uint8 array
150
+ export PRIVATE_KEY=[10,229,131,132,213,96,74,22,...]
151
+ ```
152
+
153
+ ### Client Configuration
154
+
155
+ ```python
156
+ from jup_python_sdk.clients.ultra_api_client import AsyncUltraApiClient
157
+
158
+ # With API key (for enhanced access)
159
+ client = AsyncUltraApiClient(
160
+ api_key="YOUR_API_KEY", # Get from https://portal.jup.ag/onboard
161
+ private_key_env_var="CUSTOM_PRIVATE_KEY" # Custom env var name
162
+ )
163
+
164
+ # With custom client configuration
165
+ client = AsyncUltraApiClient(
166
+ client_kwargs={
167
+ "timeout": 30, # 30 seconds timeout
168
+ "impersonate": "chrome110", # Browser impersonation
169
+ "verify": True, # SSL verification
170
+ }
171
+ )
172
+ ```
173
+
174
+ ## **API Reference**
175
+
176
+ ### UltraApiClient / AsyncUltraApiClient
177
+
178
+ The main client classes for interacting with the Jupiter Ultra API.
179
+
180
+ #### Methods
181
+
182
+ ##### `order(request: UltraOrderRequest) -> dict`
183
+
184
+ Get a swap order from the Jupiter Ultra API.
185
+
186
+ **Parameters:**
187
+
188
+ - `request`: An `UltraOrderRequest` object containing:
189
+ - `input_mint` (str): Input token mint address
190
+ - `output_mint` (str): Output token mint address
191
+ - `amount` (int): Amount in smallest unit (e.g., lamports for SOL)
192
+ - `taker` (str, optional): Taker's public key
193
+ - `referral_account` (str, optional): Referral account address
194
+ - `referral_fee` (int, optional): Referral fee in basis points
195
+
196
+ **Returns:** Dict containing order details including `requestId` and `transaction`
197
+
198
+ ##### `execute(request: UltraExecuteRequest) -> dict`
199
+
200
+ Execute a previously created order.
201
+
202
+ **Parameters:**
203
+
204
+ - `request`: An `UltraExecuteRequest` object containing:
205
+ - `request_id` (str): The request ID from the order
206
+ - `signed_transaction` (str): Base64-encoded signed transaction
207
+
208
+ **Returns:** Dict containing execution result including `signature` and `status`
209
+
210
+ ##### `order_and_execute(request: UltraOrderRequest) -> dict`
211
+
212
+ Create and execute an order in a single call.
213
+
214
+ **Parameters:**
215
+
216
+ - `request`: Same as `order()` method
217
+
218
+ **Returns:** Dict containing execution result including `signature` and `status`
219
+
220
+ ##### `balances(address: str) -> dict`
221
+
222
+ Get token balances for a Solana address.
223
+
224
+ **Parameters:**
225
+
226
+ - `address` (str): Solana public key address
227
+
228
+ **Returns:** Dict mapping token symbols to balance details:
229
+
230
+ ```python
231
+ {
232
+ "SOL": {
233
+ "amount": "100000000",
234
+ "uiAmount": 0.1,
235
+ "slot": 123456,
236
+ "isFrozen": False
237
+ }
238
+ }
239
+ ```
240
+
241
+ ##### `shield(mints: list[str]) -> dict`
242
+
243
+ Check tokens for safety warnings.
244
+
245
+ **Parameters:**
246
+
247
+ - `mints` (list[str]): List of token mint addresses to check
248
+
249
+ **Returns:** Dict containing warnings for each mint:
250
+
251
+ ```python
252
+ {
253
+ "warnings": {
254
+ "mint_address": [
255
+ {
256
+ "type": "warning_type",
257
+ "message": "Warning description"
258
+ }
259
+ ]
260
+ }
261
+ }
262
+ ```
263
+
264
+ ### Models
265
+
266
+ #### UltraOrderRequest
267
+
268
+ Pydantic model for creating swap orders.
269
+
270
+ ```python
271
+ UltraOrderRequest(
272
+ input_mint="So11111111111111111111111111111111111111112",
273
+ output_mint="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
274
+ amount=10000000,
275
+ taker="your_public_key",
276
+ referral_account="optional_referral_address",
277
+ referral_fee=50 # 0.5% in basis points
278
+ )
279
+ ```
280
+
281
+ #### UltraExecuteRequest
282
+
283
+ Pydantic model for executing orders.
284
+
285
+ ```python
286
+ UltraExecuteRequest(
287
+ request_id="order_request_id",
288
+ signed_transaction="base64_encoded_signed_transaction"
289
+ )
290
+ ```
291
+
292
+ ## **Usage Examples**
293
+
294
+ ### Check Token Balances
295
+
296
+ ```python
297
+ import asyncio
298
+ from jup_python_sdk.clients.ultra_api_client import AsyncUltraApiClient
299
+
300
+ async def check_balances():
301
+ client = AsyncUltraApiClient()
302
+
303
+ # Get your wallet address
304
+ address = await client.get_public_key()
305
+
306
+ # Fetch balances
307
+ balances = await client.balances(address)
308
+
309
+ for token, details in balances.items():
310
+ print(f"{token}: {details['uiAmount']} (frozen: {details['isFrozen']})")
311
+
312
+ await client.close()
313
+
314
+ asyncio.run(check_balances())
315
+ ```
316
+
317
+ ### Check Token Safety
318
+
319
+ ```python
320
+ import asyncio
321
+ from jup_python_sdk.clients.ultra_api_client import AsyncUltraApiClient
322
+
323
+ async def check_token_safety():
324
+ client = AsyncUltraApiClient()
325
+
326
+ # Popular tokens to check
327
+ mints = [
328
+ "So11111111111111111111111111111111111111112", # WSOL
329
+ "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", # USDC
330
+ "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263", # BONK
331
+ ]
332
+
333
+ shield_response = await client.shield(mints)
334
+
335
+ for mint, warnings in shield_response.get("warnings", {}).items():
336
+ if warnings:
337
+ print(f"⚠️ {mint} has warnings:")
338
+ for warning in warnings:
339
+ print(f" - {warning['type']}: {warning['message']}")
340
+ else:
341
+ print(f"✅ {mint} appears safe")
342
+
343
+ await client.close()
344
+
345
+ asyncio.run(check_token_safety())
346
+ ```
347
+
348
+ ### Concurrent Operations
349
+
350
+ ```python
351
+ import asyncio
352
+ from jup_python_sdk.clients.ultra_api_client import AsyncUltraApiClient
353
+
354
+ async def concurrent_operations():
355
+ client = AsyncUltraApiClient()
356
+
357
+ # Define multiple tokens to check
358
+ tokens = [
359
+ "So11111111111111111111111111111111111111112",
360
+ "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
361
+ "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
362
+ ]
363
+
364
+ # Create tasks for concurrent execution
365
+ tasks = []
366
+ for token in tokens:
367
+ task = client.shield([token])
368
+ tasks.append(task)
369
+
370
+ # Execute all requests concurrently
371
+ results = await asyncio.gather(*tasks)
372
+
373
+ # Process results
374
+ for token, result in zip(tokens, results):
375
+ print(f"Token {token}: {result}")
376
+
377
+ await client.close()
378
+
379
+ asyncio.run(concurrent_operations())
380
+ ```
381
+
382
+ ## **Best Practices**
383
+
384
+ ### 1. Always Close Clients
385
+
386
+ ```python
387
+ # Using try/finally
388
+ client = AsyncUltraApiClient()
389
+ try:
390
+ # Your code here
391
+ pass
392
+ finally:
393
+ await client.close()
394
+
395
+ # Or using async context manager (if implemented)
396
+ async with AsyncUltraApiClient() as client:
397
+ # Your code here
398
+ pass
399
+ ```
400
+
401
+ ### 2. Error Handling
402
+
403
+ ```python
404
+ try:
405
+ response = await client.order_and_execute(order_request)
406
+
407
+ if response.get("status") == "Failed":
408
+ print(f"Transaction failed: {response.get('error')}")
409
+ else:
410
+ print(f"Success: {response['signature']}")
411
+
412
+ except Exception as e:
413
+ print(f"Error occurred: {e}")
414
+ ```
415
+
416
+ ### 3. Rate Limiting
417
+
418
+ ```python
419
+ import asyncio
420
+
421
+ # Use semaphore to limit concurrent requests
422
+ semaphore = asyncio.Semaphore(5) # Max 5 concurrent requests
423
+
424
+ async def rate_limited_request(client, mint):
425
+ async with semaphore:
426
+ return await client.shield([mint])
427
+ ```
428
+
429
+ ### 4. Retry Logic
430
+
431
+ ```python
432
+ import asyncio
433
+ from typing import Optional
434
+
435
+ async def retry_request(func, max_retries=3, delay=1.0):
436
+ for attempt in range(max_retries):
437
+ try:
438
+ return await func()
439
+ except Exception as e:
440
+ if attempt == max_retries - 1:
441
+ raise
442
+ await asyncio.sleep(delay * (attempt + 1))
443
+ ```
444
+
445
+ ### 5. Token Amount Calculations
446
+
447
+ ```python
448
+ # Always work with the smallest unit (lamports for SOL)
449
+ sol_amount = 0.01 # SOL
450
+ lamports = int(sol_amount * 10**9) # Convert to lamports
451
+
452
+ # For other tokens, check their decimals
453
+ usdc_amount = 10.0 # USDC
454
+ usdc_smallest_unit = int(usdc_amount * 10**6) # USDC has 6 decimals
455
+ ```
456
+
457
+ ## **Advanced Usage**
458
+
459
+ ### Using Proxies
460
+
461
+ ```python
462
+ # SOCKS5 proxy
463
+ proxies = {"https": "socks5://user:pass@host:port"}
464
+ client = AsyncUltraApiClient(client_kwargs={"proxies": proxies})
465
+
466
+ # HTTP proxy
467
+ proxies = {
468
+ "http": "http://user:pass@proxy.example.com:8080",
469
+ "https": "http://user:pass@proxy.example.com:8080",
470
+ }
471
+ client = AsyncUltraApiClient(client_kwargs={"proxies": proxies})
472
+ ```
473
+
474
+ ### Custom DNS Resolution
475
+
476
+ ```python
477
+ # Force specific DNS resolution
478
+ client = AsyncUltraApiClient(
479
+ client_kwargs={
480
+ "resolve": ["api.jup.ag:443:1.2.3.4"],
481
+ "dns_servers": ["1.1.1.1", "1.0.0.1"],
482
+ }
483
+ )
484
+ ```
485
+
486
+ ### Custom Headers and Browser Impersonation
487
+
488
+ ```python
489
+ # Default: Uses "realworld" - randomly selects browser based on market share
490
+ client = AsyncUltraApiClient()
491
+
492
+ # Specify a specific browser version
493
+ client = AsyncUltraApiClient(
494
+ client_kwargs={
495
+ "impersonate": "chrome124", # Specific browser version
496
+ }
497
+ )
498
+
499
+ # Use latest version of a browser
500
+ client = AsyncUltraApiClient(
501
+ client_kwargs={
502
+ "impersonate": "chrome", # Latest Chrome
503
+ }
504
+ )
505
+
506
+ # Custom headers with browser impersonation
507
+ client = AsyncUltraApiClient(
508
+ client_kwargs={
509
+ "impersonate": "safari", # Latest Safari
510
+ "headers": {
511
+ "Accept-Language": "en-US,en;q=0.9",
512
+ }
513
+ }
514
+ )
515
+ ```
516
+
517
+ **Note**: By default, the SDK uses `impersonate="realworld"` which randomly selects a browser version based on current market share. This helps avoid detection and provides better anonymity.
518
+
519
+ ## **Error Handling**
520
+
521
+ The SDK may raise various exceptions:
522
+
523
+ ### Common Exceptions
524
+
525
+ ```python
526
+ try:
527
+ response = await client.order_and_execute(order_request)
528
+ except ValueError as e:
529
+ # Invalid private key format
530
+ print(f"Configuration error: {e}")
531
+ except requests.HTTPError as e:
532
+ # HTTP errors (4xx, 5xx)
533
+ print(f"API error: {e}")
534
+ except Exception as e:
535
+ # Other errors
536
+ print(f"Unexpected error: {e}")
537
+ ```
538
+
539
+ ### Response Status Handling
540
+
541
+ ```python
542
+ response = await client.order_and_execute(order_request)
543
+
544
+ if response.get("status") == "Failed":
545
+ error_code = response.get("code")
546
+ error_message = response.get("error")
547
+
548
+ if error_code == "INSUFFICIENT_BALANCE":
549
+ print("Not enough balance for the swap")
550
+ elif error_code == "SLIPPAGE_EXCEEDED":
551
+ print("Slippage tolerance exceeded")
552
+ else:
553
+ print(f"Transaction failed: {error_message}")
554
+ ```
555
+
556
+ ## **Contributing**
557
+
558
+ 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.
559
+
560
+ ### Development Setup
561
+
562
+ ```bash
563
+ # Clone the repository
564
+ git clone https://github.com/solanab/jup-python-sdk.git
565
+ cd jup-python-sdk
566
+
567
+ # Install development dependencies
568
+ pip install -e ".[dev]"
569
+
570
+ # Run tests
571
+ pytest
572
+
573
+ # Run linters
574
+ ruff check .
575
+ ruff format .
576
+ ```
577
+
578
+ ## **Resources**
579
+
580
+ - [Ultra API Documentation](https://dev.jup.ag/docs/ultra-api/)
581
+ - [Jupiter Portal](https://portal.jup.ag/onboard) - Get your API key
582
+ - [Discord Community](https://discord.gg/jup)
583
+ - [GitHub Repository](https://github.com/solanab/jup-python-sdk)
584
+
585
+ ## **License**
586
+
587
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
588
+
589
+ ## **Disclaimer**
590
+
591
+ 🚨 **This project is actively maintained.**
592
+ While we strive for stability, the SDK is under active development. We recommend staying updated with the latest releases. Important updates will be announced in the [Discord server](https://discord.gg/jup).