solanab-jup-python-sdk 2.0.3__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 (30) hide show
  1. solanab_jup_python_sdk-2.0.3/.github/workflows/ci.yml +40 -0
  2. solanab_jup_python_sdk-2.0.3/.github/workflows/release.yml +30 -0
  3. solanab_jup_python_sdk-2.0.3/.gitignore +77 -0
  4. solanab_jup_python_sdk-2.0.3/.pre-commit-config.yaml +17 -0
  5. solanab_jup_python_sdk-2.0.3/LICENSE +21 -0
  6. solanab_jup_python_sdk-2.0.3/PKG-INFO +158 -0
  7. solanab_jup_python_sdk-2.0.3/README-dev.md +16 -0
  8. solanab_jup_python_sdk-2.0.3/README-release.md +30 -0
  9. solanab_jup_python_sdk-2.0.3/README.md +125 -0
  10. solanab_jup_python_sdk-2.0.3/check_code.sh +5 -0
  11. solanab_jup_python_sdk-2.0.3/examples/advanced/concurrent_example.py +192 -0
  12. solanab_jup_python_sdk-2.0.3/examples/advanced/proxy_example.py +135 -0
  13. solanab_jup_python_sdk-2.0.3/examples/balances/async_main.py +32 -0
  14. solanab_jup_python_sdk-2.0.3/examples/balances/main.py +24 -0
  15. solanab_jup_python_sdk-2.0.3/examples/order-and-execute/async_main.py +40 -0
  16. solanab_jup_python_sdk-2.0.3/examples/order-and-execute/main.py +32 -0
  17. solanab_jup_python_sdk-2.0.3/examples/shield/async_main.py +33 -0
  18. solanab_jup_python_sdk-2.0.3/examples/shield/main.py +25 -0
  19. solanab_jup_python_sdk-2.0.3/jup_python_sdk/__init__.py +0 -0
  20. solanab_jup_python_sdk-2.0.3/jup_python_sdk/clients/__init__.py +0 -0
  21. solanab_jup_python_sdk-2.0.3/jup_python_sdk/clients/jupiter_client.py +136 -0
  22. solanab_jup_python_sdk-2.0.3/jup_python_sdk/clients/ultra_api_client.py +213 -0
  23. solanab_jup_python_sdk-2.0.3/jup_python_sdk/models/__init__.py +0 -0
  24. solanab_jup_python_sdk-2.0.3/jup_python_sdk/models/common/__init__.py +0 -0
  25. solanab_jup_python_sdk-2.0.3/jup_python_sdk/models/common/dex_enum.py +57 -0
  26. solanab_jup_python_sdk-2.0.3/jup_python_sdk/models/ultra_api/__init__.py +0 -0
  27. solanab_jup_python_sdk-2.0.3/jup_python_sdk/models/ultra_api/ultra_execute_request_model.py +16 -0
  28. solanab_jup_python_sdk-2.0.3/jup_python_sdk/models/ultra_api/ultra_order_request_model.py +20 -0
  29. solanab_jup_python_sdk-2.0.3/pyproject.toml +89 -0
  30. solanab_jup_python_sdk-2.0.3/uv.lock +1702 -0
@@ -0,0 +1,40 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
15
+
16
+ steps:
17
+ - name: Checkout Repository
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Install uv
21
+ uses: astral-sh/setup-uv@v3
22
+ with:
23
+ enable-cache: true
24
+ cache-dependency-glob: "pyproject.toml"
25
+
26
+ - name: Set up Python ${{ matrix.python-version }}
27
+ run: uv python install ${{ matrix.python-version }}
28
+
29
+ - name: Install Dependencies
30
+ run: uv sync --all-extras --dev
31
+
32
+ - name: Run Tests
33
+ env:
34
+ PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
35
+ run: uv run pytest --cov=jup_python_sdk
36
+
37
+ - name: Run Linting
38
+ run: |
39
+ uv run ruff check .
40
+ uv run ruff format --check .
@@ -0,0 +1,30 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ jobs:
9
+ build_and_publish:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ id-token: write
13
+ contents: read
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Install uv
19
+ uses: astral-sh/setup-uv@v3
20
+
21
+ - name: Set up Python
22
+ run: uv python install 3.12
23
+
24
+ - name: Build package
25
+ run: uv build
26
+
27
+ - name: Publish to PyPI
28
+ uses: pypa/gh-action-pypi-publish@release/v1
29
+ with:
30
+ password: ${{ secrets.PYPI_API_TOKEN }}
@@ -0,0 +1,77 @@
1
+ # Python artifacts
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Virtual environments
7
+ .venv/
8
+ venv/
9
+ env/
10
+ pip-wheel-metadata/
11
+ poetry.lock
12
+ Pipfile
13
+ Pipfile.lock
14
+
15
+ # Build and distribution
16
+ build/
17
+ dist/
18
+ *.egg-info/
19
+ *.egg
20
+ *.manifest
21
+ *.spec
22
+
23
+ # Hatch, Poetry & Setuptools artifacts
24
+ *.whl
25
+ *.tar.gz
26
+ *.log
27
+ .cache/
28
+ .hatch/
29
+
30
+ # IDE / Editor files
31
+ .vscode/
32
+ .idea/
33
+ *.swp
34
+ *.swo
35
+ *.swn
36
+
37
+ # Testing & Coverage
38
+ .tox/
39
+ .nox/
40
+ .coverage
41
+ coverage.xml
42
+ *.cover
43
+ htmlcov/
44
+ .pytest_cache/
45
+ pytest_cache/
46
+
47
+ # Jupyter Notebook checkpoints
48
+ .ipynb_checkpoints/
49
+
50
+ # macOS & Windows
51
+ .DS_Store
52
+ Thumbs.db
53
+
54
+ # Git metadata (if using submodules)
55
+ .gitmodules
56
+
57
+ # Pyright or MyPy type-checking cache
58
+ .pyright/
59
+ .mypy_cache/
60
+
61
+ # Generated Docs (if using Sphinx)
62
+ docs/_build/
63
+
64
+ # Ignore environment variables (if using dotenv)
65
+ .env
66
+ .env.*
67
+
68
+ # UV specific
69
+ # uv.lock # Keep lock file for reproducible builds
70
+ .python-version
71
+
72
+ # Temporary test files
73
+ test_*.py
74
+ generate_*.py
75
+
76
+ # Flake8 config
77
+ .flake8
@@ -0,0 +1,17 @@
1
+ repos:
2
+ - repo: https://github.com/psf/black
3
+ rev: 25.1.0
4
+ hooks:
5
+ - id: black
6
+ args: ["--line-length=88"]
7
+
8
+ - repo: https://github.com/PyCQA/isort
9
+ rev: 6.0.0
10
+ hooks:
11
+ - id: isort
12
+
13
+ - repo: https://github.com/PyCQA/flake8
14
+ rev: 7.1.1
15
+ hooks:
16
+ - id: flake8
17
+ args: ["--max-line-length=88"]
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Fiji
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,158 @@
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).
@@ -0,0 +1,16 @@
1
+ ## **Local Development**
2
+ If you want to make changes to the SDK and test it locally:
3
+
4
+ 1. In this project's directory, install the package in editable mode by running:
5
+ ```sh
6
+ pip install -e .
7
+ ```
8
+
9
+ 2. To use this library in another project while making changes to it, install the package from its local path in that project:
10
+ ```sh
11
+ pip install -e /path/to/jup-python-sdk
12
+ ```
13
+
14
+ Replace `/path/to/jup-python-sdk` with the absolute or relative path to this project directory.
15
+
16
+ By installing in editable mode, any changes you make to the SDK will immediately reflect in your tests without needing to reinstall the package.
@@ -0,0 +1,30 @@
1
+ ## **Making a New Release**
2
+ To create and publish a new release of the package to PyPI:
3
+
4
+ 1. **Update the Version:**
5
+ - Update the version in your `pyproject.toml` file following [semantic versioning](https://semver.org/), e.g., `0.0.1` → `0.1.0` for a minor update.
6
+
7
+ 2. **Commit the Changes:**
8
+ - Commit and push the version update to the main branch:
9
+ ```sh
10
+ git add pyproject.toml
11
+ git commit -m "Bump version to vX.Y.Z"
12
+ git push origin main
13
+ ```
14
+
15
+ 3. **Create a Tag:**
16
+ - Tag the commit with the new version:
17
+ ```sh
18
+ git tag vX.Y.Z
19
+ git push origin vX.Y.Z
20
+ ```
21
+
22
+ Replace `vX.Y.Z` with the actual version number.
23
+
24
+ 4. **GitHub Actions Workflow:**
25
+ - When the tag is pushed, the `release.yml` GitHub Actions workflow will automatically:
26
+ - Build the package using Poetry.
27
+ - Publish the package to PyPI.
28
+
29
+ 5. **Confirm the Release:**
30
+ - Check [PyPI](https://pypi.org/project/jup-python-sdk/) to ensure the new version has been published successfully.
@@ -0,0 +1,125 @@
1
+ # **Jup Python SDK**
2
+
3
+ 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>
4
+ With Ultra API, you don't need to manage or connect to any RPC endpoints, or deal with complex configurations.<br>
5
+ Everything from getting quotes to transaction execution happens directly through a powerful API.<br>
6
+
7
+ Or as we like to say around here:<br>
8
+ **"RPCs are for NPCs."**
9
+
10
+ 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/).
11
+
12
+ ## **Installation**
13
+
14
+ To install the SDK in your project, run:
15
+ ```sh
16
+ pip install jup-python-sdk
17
+ ```
18
+
19
+ ## **Quick Start (Async)**
20
+
21
+ Below is a simple asynchronous example to fetch and execute an Ultra order.
22
+
23
+ ```python
24
+ import asyncio
25
+ from dotenv import load_dotenv
26
+ from jup_python_sdk.clients.ultra_api_client import AsyncUltraApiClient
27
+ from jup_python_sdk.models.ultra_api.ultra_order_request_model import UltraOrderRequest
28
+
29
+ async def main():
30
+ load_dotenv()
31
+ # Note: For async client, methods are awaited.
32
+ client = AsyncUltraApiClient()
33
+
34
+ order_request = UltraOrderRequest(
35
+ input_mint="So11111111111111111111111111111111111111112", # WSOL
36
+ output_mint="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", # USDC
37
+ amount=10000000, # 0.01 WSOL
38
+ taker=await client.get_public_key(),
39
+ )
40
+
41
+ try:
42
+ client_response = await client.order_and_execute(order_request)
43
+ signature = str(client_response["signature"])
44
+
45
+ print("Order and Execute API Response:")
46
+ print(f" - Status: {client_response.get('status')}")
47
+ if client_response.get("status") == "Failed":
48
+ print(f" - Code: {client_response.get('code')}")
49
+ print(f" - Error: {client_response.get('error')}")
50
+
51
+ print(f" - Transaction Signature: {signature}")
52
+ print(f" - View on Solscan: https://solscan.io/tx/{signature}")
53
+
54
+ except Exception as e:
55
+ print("Error occurred while processing the swap:", str(e))
56
+ finally:
57
+ await client.close()
58
+
59
+ if __name__ == "__main__":
60
+ asyncio.run(main())
61
+ ```
62
+
63
+ > **Note**: A synchronous client (`UltraApiClient`) is also available. See the [examples](./examples) folder for both sync and async usage.
64
+
65
+ ## **Setup Instructions**
66
+
67
+ Before using the SDK, please ensure you have completed the following steps:
68
+
69
+ 1. **Environment Variables**:
70
+ Set up your required environment variables.
71
+ The SDK supports both base58 string and uint8 array formats for your private key.
72
+ ```sh
73
+ # Base58 format
74
+ export PRIVATE_KEY=your_base58_private_key_here
75
+
76
+ # OR as a uint8 array
77
+ export PRIVATE_KEY=[10,229,131,132,213,96,74,22,...]
78
+ ```
79
+
80
+ > **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.
81
+
82
+ 2. **Optional Configuration**:
83
+ Depending on your credentials and setup, you have a couple of options for initializing the `UltraApiClient`:
84
+ - **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.
85
+ - **Custom Private Key Env Var**: Specify a different environment variable name for your private key.
86
+
87
+ ```python
88
+ from jup_python_sdk.clients.ultra_api_client import AsyncUltraApiClient
89
+
90
+ client = AsyncUltraApiClient(
91
+ api_key="YOUR_API_KEY",
92
+ private_key_env_var="YOUR_CUSTOM_ENV_VAR"
93
+ )
94
+ ```
95
+
96
+ ## **Advanced Configuration (Proxies, Custom DNS)**
97
+
98
+ The SDK is built on `curl_cffi`, allowing you to pass any valid `curl_cffi` client parameter during initialization for advanced network control.
99
+
100
+ ### Using a SOCKS5 Proxy
101
+
102
+ ```python
103
+ from jup_python_sdk.clients.ultra_api_client import AsyncUltraApiClient
104
+
105
+ proxies = {"httpss": "socks5://user:pass@host:port"}
106
+ client = AsyncUltraApiClient(client_kwargs={"proxies": proxies, "impersonate": "chrome110"})
107
+ ```
108
+
109
+ ### Using Custom DNS Resolution
110
+
111
+ This is useful for bypassing local DNS caches or using a specialized DNS resolver.
112
+
113
+ ```python
114
+ from jup_python_sdk.clients.ultra_api_client import AsyncUltraApiClient
115
+
116
+ # Tell the client to resolve jup.ag to a specific IP address
117
+ resolve_string = "jup.ag:443:1.2.3.4"
118
+ client = AsyncUltraApiClient(client_kwargs={"resolve": [resolve_string]})
119
+ ```
120
+
121
+ ## **Disclaimer**
122
+
123
+ 🚨 **This project is actively worked on.**
124
+ While we don't expect breaking changes as the SDK evolves, we recommend you stay updated with the latest releases.
125
+ Any important updates will be announced in the [Discord server](https://discord.gg/jup).
@@ -0,0 +1,5 @@
1
+ black jup_python_sdk tests --line-length 79
2
+ isort jup_python_sdk tests
3
+ flake8 jup_python_sdk tests
4
+ mypy jup_python_sdk tests
5
+ pytest