Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 66 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,48 @@ on:
- 'releases/*'

jobs:
# ============================================
# DEPENDENCY CHECK JOB
# Ensures all imports are satisfied by requirements.txt
# ============================================
dependency-check:
name: Dependency Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install only from requirements.txt (clean environment)
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Verify all production imports work
run: |
# This catches missing dependencies in requirements.txt
python -c "
import okx
from okx import Account, Trade, Funding, MarketData, PublicData
from okx import SubAccount, Convert, BlockTrading, CopyTrading
from okx import SpreadTrading, Grid, TradingData, Status
from okx.websocket import WsPublicAsync, WsPrivateAsync
print('✅ All imports successful')
print(f' okx version: {okx.__version__}')
"

- name: Verify test imports
run: |
pip install pytest
python -c "
import pytest
import unittest
print('✅ Test imports successful')
"

# ============================================
# LINT JOB
# ============================================
Expand All @@ -31,11 +73,11 @@ jobs:
- name: Install linting tools
run: |
python -m pip install --upgrade pip
pip install flake8
pip install ruff

- name: Run flake8
- name: Run ruff
run: |
flake8 okx/ --max-line-length=120 --ignore=E501,W503,E203 --count --show-source --statistics
ruff check okx/ --ignore=E501
continue-on-error: true # Set to false once codebase is cleaned up

# ============================================
Expand All @@ -44,10 +86,12 @@ jobs:
test:
name: Test (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
needs: [dependency-check] # Only run tests if dependencies are valid
strategy:
fail-fast: false
fail-fast: true
max-parallel: 1
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]
python-version: ["3.9", "3.12"]

steps:
- uses: actions/checkout@v4
Expand All @@ -61,23 +105,23 @@ jobs:
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('setup.py') }}
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-${{ matrix.python-version }}-
${{ runner.os }}-pip-

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -e .
pip install pytest pytest-cov pytest-asyncio websockets certifi

- name: Run tests
run: |
python -m pytest test/unit/ -v --cov=okx --cov-report=term-missing --cov-report=xml

- name: Upload coverage to Codecov
if: matrix.python-version == '3.11'
if: matrix.python-version == '3.12'
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
Expand All @@ -99,21 +143,31 @@ jobs:
with:
python-version: "3.11"

- name: Install build tools
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
pip install -r requirements.txt

- name: Build package
run: python -m build
run: python -m build --no-isolation

- name: Check package
run: twine check dist/*

- name: Test install from wheel (clean environment)
run: |
# Create a fresh venv and install the built wheel
python -m venv /tmp/test-install
/tmp/test-install/bin/pip install dist/*.whl
/tmp/test-install/bin/python -c "
import okx
from okx import Account, Trade, Funding
print(f'✅ Package installs correctly: okx {okx.__version__}')
"

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
retention-days: 7

3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include requirements.txt
include README.md

72 changes: 66 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,80 @@ Make sure you update often and check the [Changelog](https://www.okx.com/docs-v5
### Quick start
#### Prerequisites

`python version:>=3.9`
`python version:>=3.7`

`WebSocketAPI: websockets package advise version 6.0`

#### Step 1: register an account on OKX and apply for an API key
#### Step 1: Register an account on OKX and apply for an API key
- Register for an account: https://www.okx.com/account/register
- Apply for an API key: https://www.okx.com/account/users/myApi

#### Step 2: install python-okx
#### Step 2: Install python-okx

```python
```bash
pip install python-okx
```

### API Credentials

#### Option 1: Hardcoded credentials

```python
from okx import Account

account = Account.AccountAPI(
api_key="your-api-key-here",
api_secret_key="your-api-secret-here",
passphrase="your-passphrase-here",
flag="1", # 0 = live trading, 1 = demo trading
debug=False
)
```

#### Option 2: Using `.env` file (recommended)

Create a `.env` file in your project root:

```bash
OKX_API_KEY=your-api-key-here
OKX_API_SECRET=your-api-secret-here
OKX_PASSPHRASE=your-passphrase-here
OKX_FLAG=1
```

Then load it in your code:

```python
import os
from dotenv import load_dotenv
from okx import Account

load_dotenv()

account = Account.AccountAPI(
api_key=os.getenv('OKX_API_KEY'),
api_secret_key=os.getenv('OKX_API_SECRET'),
passphrase=os.getenv('OKX_PASSPHRASE'),
flag=os.getenv('OKX_FLAG', '1'),
debug=False
)
```

### Development Setup

For contributors or local development:

```bash
# Clone the repository
git clone https://github.com/okxapi/python-okx.git
cd python-okx

# Install dependencies
pip install -r requirements.txt
pip install -e .

# Run tests
pytest test/unit/ -v
```

#### Step 3: Run examples

- Fill in API credentials in the corresponding examples
Expand Down
15 changes: 15 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Dependencies for python-okx
httpx[http2]>=0.24.0
requests>=2.25.0
websockets>=10.0
certifi>=2021.0.0
loguru>=0.7.0
python-dotenv>=1.0.0

# Development & Testing
pytest>=7.0.0
pytest-asyncio>=0.21.0
pytest-cov>=4.0.0
ruff>=0.1.0
build>=1.0.0
twine>=4.0.0
56 changes: 42 additions & 14 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,39 @@
import os
import setuptools

# Get the directory where setup.py is located
HERE = os.path.dirname(os.path.abspath(__file__))

# Read version from package
import okx
with open("README.md", "r",encoding="utf-8") as fh:

# Read README
with open(os.path.join(HERE, "README.md"), "r", encoding="utf-8") as fh:
long_description = fh.read()


def parse_requirements():
"""Parse requirements from requirements.txt."""
requirements = []
req_path = os.path.join(HERE, "requirements.txt")

if not os.path.exists(req_path):
return requirements

with open(req_path, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
# Skip empty lines and comments
if not line or line.startswith("#"):
continue
# Handle inline comments
if "#" in line:
line = line.split("#")[0].strip()
requirements.append(line)

return requirements


setuptools.setup(
name="python-okx",
version=okx.__version__,
Expand All @@ -12,21 +43,18 @@
long_description=long_description,
long_description_content_type="text/markdown",
url="https://okx.com/docs-v5/",
packages=setuptools.find_packages(),
packages=setuptools.find_packages(exclude=["test", "test.*", "example"]),
python_requires=">=3.7",
classifiers=[
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
install_requires=[
"importlib-metadata",
"httpx[http2]",
"keyring",
"loguru",
"requests",
"Twisted",
"pyOpenSSL",
"websockets",
"certifi"
]
)
install_requires=parse_requirements(),
)
Loading