solanab-jup-python-sdk 2.0.3__py3-none-any.whl → 2.0.6__py3-none-any.whl
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.
- jup_python_sdk/clients/jupiter_client.py +102 -2
- jup_python_sdk/models/common/dex_enum.py +13 -0
- jup_python_sdk/models/ultra_api/ultra_execute_request_model.py +14 -0
- jup_python_sdk/models/ultra_api/ultra_order_request_model.py +18 -0
- solanab_jup_python_sdk-2.0.6.dist-info/METADATA +592 -0
- {solanab_jup_python_sdk-2.0.3.dist-info → solanab_jup_python_sdk-2.0.6.dist-info}/RECORD +8 -8
- solanab_jup_python_sdk-2.0.3.dist-info/METADATA +0 -158
- {solanab_jup_python_sdk-2.0.3.dist-info → solanab_jup_python_sdk-2.0.6.dist-info}/WHEEL +0 -0
- {solanab_jup_python_sdk-2.0.3.dist-info → solanab_jup_python_sdk-2.0.6.dist-info}/licenses/LICENSE +0 -0
@@ -15,11 +15,26 @@ class _CoreJupiterClient:
|
|
15
15
|
"""
|
16
16
|
|
17
17
|
def __init__(self, api_key: Optional[str], private_key_env_var: str):
|
18
|
+
"""
|
19
|
+
Initialize the core Jupiter client.
|
20
|
+
|
21
|
+
Args:
|
22
|
+
api_key: Optional API key for enhanced access to Jupiter API.
|
23
|
+
If provided, uses https://api.jup.ag endpoint.
|
24
|
+
private_key_env_var: Name of environment variable containing the
|
25
|
+
private key. Defaults to 'PRIVATE_KEY'.
|
26
|
+
"""
|
18
27
|
self.api_key = api_key
|
19
28
|
self.base_url = "https://api.jup.ag" if api_key else "https://lite-api.jup.ag"
|
20
29
|
self.private_key_env_var = private_key_env_var
|
21
30
|
|
22
31
|
def _get_headers(self) -> dict[str, str]:
|
32
|
+
"""
|
33
|
+
Get headers for GET requests.
|
34
|
+
|
35
|
+
Returns:
|
36
|
+
Dict containing headers with Accept and optional API key.
|
37
|
+
"""
|
23
38
|
headers = {
|
24
39
|
"Accept": "application/json",
|
25
40
|
}
|
@@ -28,6 +43,12 @@ class _CoreJupiterClient:
|
|
28
43
|
return headers
|
29
44
|
|
30
45
|
def _post_headers(self) -> dict[str, str]:
|
46
|
+
"""
|
47
|
+
Get headers for POST requests.
|
48
|
+
|
49
|
+
Returns:
|
50
|
+
Dict containing headers with Accept, Content-Type, and optional API key.
|
51
|
+
"""
|
31
52
|
headers = {
|
32
53
|
"Accept": "application/json",
|
33
54
|
"Content-Type": "application/json",
|
@@ -58,13 +79,34 @@ class _CoreJupiterClient:
|
|
58
79
|
raise ValueError(f"Invalid base58 private key format: {e}") from e
|
59
80
|
|
60
81
|
def get_public_key(self) -> str:
|
82
|
+
"""
|
83
|
+
Get the public key from the loaded private key.
|
84
|
+
|
85
|
+
Returns:
|
86
|
+
Public key as a base58-encoded string.
|
87
|
+
"""
|
61
88
|
wallet = Keypair.from_bytes(self._load_private_key_bytes())
|
62
89
|
return str(wallet.pubkey())
|
63
90
|
|
64
91
|
async def get_public_key_async(self) -> str:
|
92
|
+
"""
|
93
|
+
Async wrapper for get_public_key().
|
94
|
+
|
95
|
+
Returns:
|
96
|
+
Public key as a base58-encoded string.
|
97
|
+
"""
|
65
98
|
return self.get_public_key()
|
66
99
|
|
67
100
|
def _sign_base64_transaction(self, transaction_base64: str) -> VersionedTransaction:
|
101
|
+
"""
|
102
|
+
Sign a base64-encoded transaction.
|
103
|
+
|
104
|
+
Args:
|
105
|
+
transaction_base64: Base64-encoded transaction string.
|
106
|
+
|
107
|
+
Returns:
|
108
|
+
Signed VersionedTransaction object.
|
109
|
+
"""
|
68
110
|
transaction_bytes = base64.b64decode(transaction_base64)
|
69
111
|
versioned_transaction = VersionedTransaction.from_bytes(transaction_bytes)
|
70
112
|
return self._sign_versioned_transaction(versioned_transaction)
|
@@ -72,6 +114,15 @@ class _CoreJupiterClient:
|
|
72
114
|
def _sign_versioned_transaction(
|
73
115
|
self, versioned_transaction: VersionedTransaction
|
74
116
|
) -> VersionedTransaction:
|
117
|
+
"""
|
118
|
+
Sign a VersionedTransaction with the loaded private key.
|
119
|
+
|
120
|
+
Args:
|
121
|
+
versioned_transaction: VersionedTransaction to sign.
|
122
|
+
|
123
|
+
Returns:
|
124
|
+
Signed VersionedTransaction with signature applied.
|
125
|
+
"""
|
75
126
|
wallet = Keypair.from_bytes(self._load_private_key_bytes())
|
76
127
|
account_keys = versioned_transaction.message.account_keys
|
77
128
|
wallet_index = account_keys.index(wallet.pubkey())
|
@@ -87,6 +138,15 @@ class _CoreJupiterClient:
|
|
87
138
|
def _serialize_versioned_transaction(
|
88
139
|
self, versioned_transaction: VersionedTransaction
|
89
140
|
) -> str:
|
141
|
+
"""
|
142
|
+
Serialize a VersionedTransaction to base64 string.
|
143
|
+
|
144
|
+
Args:
|
145
|
+
versioned_transaction: VersionedTransaction to serialize.
|
146
|
+
|
147
|
+
Returns:
|
148
|
+
Base64-encoded string representation of the transaction.
|
149
|
+
"""
|
90
150
|
return base64.b64encode(bytes(versioned_transaction)).decode("utf-8")
|
91
151
|
|
92
152
|
|
@@ -102,12 +162,29 @@ class JupiterClient(_CoreJupiterClient):
|
|
102
162
|
private_key_env_var: str = "PRIVATE_KEY",
|
103
163
|
client_kwargs: Optional[dict[str, Any]] = None,
|
104
164
|
):
|
165
|
+
"""
|
166
|
+
Initialize the synchronous Jupiter client.
|
167
|
+
|
168
|
+
Args:
|
169
|
+
api_key: Optional API key for enhanced access to Jupiter API.
|
170
|
+
private_key_env_var: Name of environment variable containing the
|
171
|
+
private key.
|
172
|
+
client_kwargs: Optional kwargs to pass to curl_cffi Session.
|
173
|
+
Common options include 'proxies', 'timeout', 'impersonate'.
|
174
|
+
"""
|
105
175
|
super().__init__(api_key, private_key_env_var)
|
106
176
|
kwargs = client_kwargs or {}
|
107
|
-
|
177
|
+
# Use realworld random browser impersonation based on market share
|
178
|
+
# if not specified
|
179
|
+
kwargs.setdefault("impersonate", "realworld")
|
108
180
|
self.client = requests.Session(**kwargs)
|
109
181
|
|
110
182
|
def close(self) -> None:
|
183
|
+
"""
|
184
|
+
Close the underlying HTTP session.
|
185
|
+
|
186
|
+
Always call this method when done to properly cleanup resources.
|
187
|
+
"""
|
111
188
|
self.client.close()
|
112
189
|
|
113
190
|
|
@@ -123,14 +200,37 @@ class AsyncJupiterClient(_CoreJupiterClient):
|
|
123
200
|
private_key_env_var: str = "PRIVATE_KEY",
|
124
201
|
client_kwargs: Optional[dict[str, Any]] = None,
|
125
202
|
):
|
203
|
+
"""
|
204
|
+
Initialize the asynchronous Jupiter client.
|
205
|
+
|
206
|
+
Args:
|
207
|
+
api_key: Optional API key for enhanced access to Jupiter API.
|
208
|
+
private_key_env_var: Name of environment variable containing the
|
209
|
+
private key.
|
210
|
+
client_kwargs: Optional kwargs to pass to curl_cffi AsyncSession.
|
211
|
+
Common options include 'proxies', 'timeout', 'impersonate'.
|
212
|
+
"""
|
126
213
|
super().__init__(api_key, private_key_env_var)
|
127
214
|
kwargs = client_kwargs or {}
|
128
|
-
|
215
|
+
# Use realworld random browser impersonation based on market share
|
216
|
+
# if not specified
|
217
|
+
kwargs.setdefault("impersonate", "realworld")
|
129
218
|
self.client = AsyncSession(**kwargs)
|
130
219
|
|
131
220
|
async def close(self) -> None:
|
221
|
+
"""
|
222
|
+
Close the underlying HTTP session.
|
223
|
+
|
224
|
+
Always call this method when done to properly cleanup resources.
|
225
|
+
"""
|
132
226
|
await self.client.close()
|
133
227
|
|
134
228
|
# Override get_public_key for async context consistency
|
135
229
|
async def get_public_key(self) -> str: # type: ignore[override]
|
230
|
+
"""
|
231
|
+
Get the public key from the loaded private key.
|
232
|
+
|
233
|
+
Returns:
|
234
|
+
Public key as a base58-encoded string.
|
235
|
+
"""
|
136
236
|
return super().get_public_key()
|
@@ -3,6 +3,13 @@ from urllib.parse import quote
|
|
3
3
|
|
4
4
|
|
5
5
|
class DexEnum(str, Enum):
|
6
|
+
"""
|
7
|
+
Enumeration of supported DEXes (Decentralized Exchanges) on Jupiter.
|
8
|
+
|
9
|
+
Each value represents a different liquidity source that Jupiter can route through.
|
10
|
+
The string values are URL-encoded when used in API requests.
|
11
|
+
"""
|
12
|
+
|
6
13
|
WOOFI = "Woofi"
|
7
14
|
PUMP_FUN = "Pump.fun"
|
8
15
|
WHIRLPOOL = "Whirlpool"
|
@@ -54,4 +61,10 @@ class DexEnum(str, Enum):
|
|
54
61
|
GUACSWAP = "Guacswap"
|
55
62
|
|
56
63
|
def __str__(self) -> str:
|
64
|
+
"""
|
65
|
+
Return URL-encoded string representation of the DEX name.
|
66
|
+
|
67
|
+
Returns:
|
68
|
+
URL-encoded DEX name suitable for API requests.
|
69
|
+
"""
|
57
70
|
return quote(self.value)
|
@@ -5,10 +5,24 @@ from pydantic.alias_generators import to_camel
|
|
5
5
|
|
6
6
|
|
7
7
|
class UltraExecuteRequest(BaseModel):
|
8
|
+
"""
|
9
|
+
Pydantic model for executing a previously created order.
|
10
|
+
|
11
|
+
Attributes:
|
12
|
+
signed_transaction: Base64-encoded signed transaction string.
|
13
|
+
request_id: The request ID returned from the order endpoint.
|
14
|
+
"""
|
15
|
+
|
8
16
|
signed_transaction: str
|
9
17
|
request_id: str
|
10
18
|
|
11
19
|
def to_dict(self) -> dict[str, Any]:
|
20
|
+
"""
|
21
|
+
Convert the model to a dictionary with camelCase keys.
|
22
|
+
|
23
|
+
Returns:
|
24
|
+
Dict with camelCase keys suitable for API requests.
|
25
|
+
"""
|
12
26
|
params = self.model_dump(exclude_none=True)
|
13
27
|
|
14
28
|
camel_case_params = {to_camel(key): value for key, value in params.items()}
|
@@ -5,6 +5,18 @@ from pydantic.alias_generators import to_camel
|
|
5
5
|
|
6
6
|
|
7
7
|
class UltraOrderRequest(BaseModel):
|
8
|
+
"""
|
9
|
+
Pydantic model for creating swap orders on Jupiter Ultra API.
|
10
|
+
|
11
|
+
Attributes:
|
12
|
+
input_mint: Mint address of the input token.
|
13
|
+
output_mint: Mint address of the output token.
|
14
|
+
amount: Amount to swap in the smallest unit (e.g., lamports for SOL).
|
15
|
+
taker: Optional public key of the taker (usually your wallet address).
|
16
|
+
referral_account: Optional referral account address for fee sharing.
|
17
|
+
referral_fee: Optional referral fee in basis points (1 bp = 0.01%).
|
18
|
+
"""
|
19
|
+
|
8
20
|
input_mint: str
|
9
21
|
output_mint: str
|
10
22
|
amount: int
|
@@ -13,6 +25,12 @@ class UltraOrderRequest(BaseModel):
|
|
13
25
|
referral_fee: Optional[int] = None
|
14
26
|
|
15
27
|
def to_dict(self) -> dict[str, Any]:
|
28
|
+
"""
|
29
|
+
Convert the model to a dictionary with camelCase keys.
|
30
|
+
|
31
|
+
Returns:
|
32
|
+
Dict with camelCase keys suitable for API requests.
|
33
|
+
"""
|
16
34
|
params = self.model_dump(exclude_none=True)
|
17
35
|
|
18
36
|
camel_case_params = {to_camel(key): value for key, value in params.items()}
|
@@ -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
|
+
[](https://badge.fury.io/py/solanab-jup-python-sdk)
|
42
|
+
[](https://pypi.org/project/solanab-jup-python-sdk/)
|
43
|
+
[](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).
|
@@ -1,14 +1,14 @@
|
|
1
1
|
jup_python_sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
2
|
jup_python_sdk/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
-
jup_python_sdk/clients/jupiter_client.py,sha256=
|
3
|
+
jup_python_sdk/clients/jupiter_client.py,sha256=9XXruDRIyFs8n3H2RsU0FhaihF--9mzNwMDs0ldiYPA,7762
|
4
4
|
jup_python_sdk/clients/ultra_api_client.py,sha256=jgNgf04bDSJxu8MY1oGRx3Bxemyy4B4y5eUuQBN61qA,6750
|
5
5
|
jup_python_sdk/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
6
|
jup_python_sdk/models/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
-
jup_python_sdk/models/common/dex_enum.py,sha256=
|
7
|
+
jup_python_sdk/models/common/dex_enum.py,sha256=ie9bTkVYTdNZijwLB4mCZ-AN3g-cV5OahXke1z8V0PY,1921
|
8
8
|
jup_python_sdk/models/ultra_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
jup_python_sdk/models/ultra_api/ultra_execute_request_model.py,sha256=
|
10
|
-
jup_python_sdk/models/ultra_api/ultra_order_request_model.py,sha256=
|
11
|
-
solanab_jup_python_sdk-2.0.
|
12
|
-
solanab_jup_python_sdk-2.0.
|
13
|
-
solanab_jup_python_sdk-2.0.
|
14
|
-
solanab_jup_python_sdk-2.0.
|
9
|
+
jup_python_sdk/models/ultra_api/ultra_execute_request_model.py,sha256=jgvBjzVwslq1aItsxOJX9BWechEGiJq8Nr4H3om352I,806
|
10
|
+
jup_python_sdk/models/ultra_api/ultra_order_request_model.py,sha256=gv_xxvVjQVbD9NSJa3d06WMe9MkTK31KkKmKq0e7UOc,1221
|
11
|
+
solanab_jup_python_sdk-2.0.6.dist-info/METADATA,sha256=P0T43FXZAWo-Vm8Fx_zMWNacHCZhqbYxcTMieFHOIMQ,15957
|
12
|
+
solanab_jup_python_sdk-2.0.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
13
|
+
solanab_jup_python_sdk-2.0.6.dist-info/licenses/LICENSE,sha256=3va7FgUbc2istAEEchr1jkoUjBoSYPMkguY1BGuHt2U,1061
|
14
|
+
solanab_jup_python_sdk-2.0.6.dist-info/RECORD,,
|
@@ -1,158 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: solanab-jup-python-sdk
|
3
|
-
Version: 2.0.3
|
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: Operating System :: OS Independent
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
13
|
-
Requires-Python: >=3.9
|
14
|
-
Requires-Dist: base58>=2.1.1
|
15
|
-
Requires-Dist: curl-cffi>=0.12
|
16
|
-
Requires-Dist: pydantic>=2.11.3
|
17
|
-
Requires-Dist: solana>=0.36.6
|
18
|
-
Requires-Dist: solders>=0.26.0
|
19
|
-
Provides-Extra: dev
|
20
|
-
Requires-Dist: bandit>=1.7; extra == 'dev'
|
21
|
-
Requires-Dist: black>=25.1.0; extra == 'dev'
|
22
|
-
Requires-Dist: flake8>=7.1.1; extra == 'dev'
|
23
|
-
Requires-Dist: isort>=6.0.0; extra == 'dev'
|
24
|
-
Requires-Dist: mypy>=1.15.0; extra == 'dev'
|
25
|
-
Requires-Dist: pre-commit>=4.1.0; extra == 'dev'
|
26
|
-
Requires-Dist: pytest-asyncio>=0.23.7; extra == 'dev'
|
27
|
-
Requires-Dist: pytest-cov>=6.1.1; extra == 'dev'
|
28
|
-
Requires-Dist: pytest>=8.3.4; extra == 'dev'
|
29
|
-
Requires-Dist: python-dotenv>=1.1.0; extra == 'dev'
|
30
|
-
Requires-Dist: responses>=0.25.6; extra == 'dev'
|
31
|
-
Requires-Dist: safety>=2.3; extra == 'dev'
|
32
|
-
Description-Content-Type: text/markdown
|
33
|
-
|
34
|
-
# **Jup Python SDK**
|
35
|
-
|
36
|
-
A high-performance, async-first Python SDK for seamless interaction with the Jupiter Ultra API, powered by `curl_cffi` for maximum speed and flexibility.<br>
|
37
|
-
With Ultra API, you don't need to manage or connect to any RPC endpoints, or deal with complex configurations.<br>
|
38
|
-
Everything from getting quotes to transaction execution happens directly through a powerful API.<br>
|
39
|
-
|
40
|
-
Or as we like to say around here:<br>
|
41
|
-
**"RPCs are for NPCs."**
|
42
|
-
|
43
|
-
For a deeper understanding of the Ultra API, including its features and benefits, check out the [Ultra API Docs](https://dev.jup.ag/docs/ultra-api/).
|
44
|
-
|
45
|
-
## **Installation**
|
46
|
-
|
47
|
-
To install the SDK in your project, run:
|
48
|
-
```sh
|
49
|
-
pip install jup-python-sdk
|
50
|
-
```
|
51
|
-
|
52
|
-
## **Quick Start (Async)**
|
53
|
-
|
54
|
-
Below is a simple asynchronous example to fetch and execute an Ultra order.
|
55
|
-
|
56
|
-
```python
|
57
|
-
import asyncio
|
58
|
-
from dotenv import load_dotenv
|
59
|
-
from jup_python_sdk.clients.ultra_api_client import AsyncUltraApiClient
|
60
|
-
from jup_python_sdk.models.ultra_api.ultra_order_request_model import UltraOrderRequest
|
61
|
-
|
62
|
-
async def main():
|
63
|
-
load_dotenv()
|
64
|
-
# Note: For async client, methods are awaited.
|
65
|
-
client = AsyncUltraApiClient()
|
66
|
-
|
67
|
-
order_request = UltraOrderRequest(
|
68
|
-
input_mint="So11111111111111111111111111111111111111112", # WSOL
|
69
|
-
output_mint="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", # USDC
|
70
|
-
amount=10000000, # 0.01 WSOL
|
71
|
-
taker=await client.get_public_key(),
|
72
|
-
)
|
73
|
-
|
74
|
-
try:
|
75
|
-
client_response = await client.order_and_execute(order_request)
|
76
|
-
signature = str(client_response["signature"])
|
77
|
-
|
78
|
-
print("Order and Execute API Response:")
|
79
|
-
print(f" - Status: {client_response.get('status')}")
|
80
|
-
if client_response.get("status") == "Failed":
|
81
|
-
print(f" - Code: {client_response.get('code')}")
|
82
|
-
print(f" - Error: {client_response.get('error')}")
|
83
|
-
|
84
|
-
print(f" - Transaction Signature: {signature}")
|
85
|
-
print(f" - View on Solscan: https://solscan.io/tx/{signature}")
|
86
|
-
|
87
|
-
except Exception as e:
|
88
|
-
print("Error occurred while processing the swap:", str(e))
|
89
|
-
finally:
|
90
|
-
await client.close()
|
91
|
-
|
92
|
-
if __name__ == "__main__":
|
93
|
-
asyncio.run(main())
|
94
|
-
```
|
95
|
-
|
96
|
-
> **Note**: A synchronous client (`UltraApiClient`) is also available. See the [examples](./examples) folder for both sync and async usage.
|
97
|
-
|
98
|
-
## **Setup Instructions**
|
99
|
-
|
100
|
-
Before using the SDK, please ensure you have completed the following steps:
|
101
|
-
|
102
|
-
1. **Environment Variables**:
|
103
|
-
Set up your required environment variables.
|
104
|
-
The SDK supports both base58 string and uint8 array formats for your private key.
|
105
|
-
```sh
|
106
|
-
# Base58 format
|
107
|
-
export PRIVATE_KEY=your_base58_private_key_here
|
108
|
-
|
109
|
-
# OR as a uint8 array
|
110
|
-
export PRIVATE_KEY=[10,229,131,132,213,96,74,22,...]
|
111
|
-
```
|
112
|
-
|
113
|
-
> **Note**: `PRIVATE_KEY` can be either a base58-encoded string (default Solana format), or a uint8 array (e.g. `[181,99,240,...]`). The SDK will automatically detect and parse the format.
|
114
|
-
|
115
|
-
2. **Optional Configuration**:
|
116
|
-
Depending on your credentials and setup, you have a couple of options for initializing the `UltraApiClient`:
|
117
|
-
- **API Key**: Use an API key from [the Jupiter Portal](https://portal.jup.ag/onboard) for enhanced access. This will use the `https://api.jup.ag/` endpoint.
|
118
|
-
- **Custom Private Key Env Var**: Specify a different environment variable name for your private key.
|
119
|
-
|
120
|
-
```python
|
121
|
-
from jup_python_sdk.clients.ultra_api_client import AsyncUltraApiClient
|
122
|
-
|
123
|
-
client = AsyncUltraApiClient(
|
124
|
-
api_key="YOUR_API_KEY",
|
125
|
-
private_key_env_var="YOUR_CUSTOM_ENV_VAR"
|
126
|
-
)
|
127
|
-
```
|
128
|
-
|
129
|
-
## **Advanced Configuration (Proxies, Custom DNS)**
|
130
|
-
|
131
|
-
The SDK is built on `curl_cffi`, allowing you to pass any valid `curl_cffi` client parameter during initialization for advanced network control.
|
132
|
-
|
133
|
-
### Using a SOCKS5 Proxy
|
134
|
-
|
135
|
-
```python
|
136
|
-
from jup_python_sdk.clients.ultra_api_client import AsyncUltraApiClient
|
137
|
-
|
138
|
-
proxies = {"httpss": "socks5://user:pass@host:port"}
|
139
|
-
client = AsyncUltraApiClient(client_kwargs={"proxies": proxies, "impersonate": "chrome110"})
|
140
|
-
```
|
141
|
-
|
142
|
-
### Using Custom DNS Resolution
|
143
|
-
|
144
|
-
This is useful for bypassing local DNS caches or using a specialized DNS resolver.
|
145
|
-
|
146
|
-
```python
|
147
|
-
from jup_python_sdk.clients.ultra_api_client import AsyncUltraApiClient
|
148
|
-
|
149
|
-
# Tell the client to resolve jup.ag to a specific IP address
|
150
|
-
resolve_string = "jup.ag:443:1.2.3.4"
|
151
|
-
client = AsyncUltraApiClient(client_kwargs={"resolve": [resolve_string]})
|
152
|
-
```
|
153
|
-
|
154
|
-
## **Disclaimer**
|
155
|
-
|
156
|
-
🚨 **This project is actively worked on.**
|
157
|
-
While we don't expect breaking changes as the SDK evolves, we recommend you stay updated with the latest releases.
|
158
|
-
Any important updates will be announced in the [Discord server](https://discord.gg/jup).
|
File without changes
|
{solanab_jup_python_sdk-2.0.3.dist-info → solanab_jup_python_sdk-2.0.6.dist-info}/licenses/LICENSE
RENAMED
File without changes
|