Skip to content
Open
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
40 changes: 40 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python

# Virtual environments
venv/
env/
ENV/
.venv

# Environment variables
.env

# Distribution / packaging
build/
dist/
*.egg-info/
.eggs/

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
Thumbs.db

# Testing
.pytest_cache/
.coverage
htmlcov/

# Ruff
.ruff_cache/
51 changes: 51 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
.PHONY: generate generate-types generate-http test format typecheck install clean help

help:
@echo "Available commands:"
@echo " make generate - Generate all code (types + HTTP client)"
@echo " make generate-types - Generate type definitions"
@echo " make generate-http - Generate HTTP client"
@echo " make test - Run tests"
@echo " make format - Format all Python files with ruff"
@echo " make typecheck - Run mypy type checking"
@echo " make install - Install all packages in dev mode"
@echo " make clean - Remove generated files and caches"

generate: generate-types generate-http

generate-types:
@echo "🔧 Generating types..."
@python codegen/types/generate_types.py

generate-http:
@echo "🔧 Generating HTTP client..."
@python codegen/http/generate_http.py

test:
@echo "🧪 Running tests..."
@pytest packages/*/tests/ -v

format:
@echo "🎨 Formatting code..."
@ruff format .

typecheck:
@echo "🔍 Running type checks..."
@mypy packages/
@echo "✅ Type checking complete"

install:
@echo "📦 Installing packages in dev mode..."
@pip install -e .[dev]
@pip install -e ./packages/sdk-types[dev]
@pip install -e ./packages/api-key-stamper[dev]
@pip install -e ./packages/http[dev]
@echo "✅ All packages installed"

clean:
@echo "🧹 Cleaning up..."
@find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
@find . -type d -name "*.egg-info" -exec rm -rf {} + 2>/dev/null || true
@find . -type d -name ".pytest_cache" -exec rm -rf {} + 2>/dev/null || true
@find . -type d -name ".ruff_cache" -exec rm -rf {} + 2>/dev/null || true
@echo "✅ Cleanup complete"
122 changes: 111 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,119 @@
# python-sdk
This repository contains support for interacting with the Turnkey API using Python
# Turnkey Python SDK

Unlike other languages ([Typescript](https://github.com/tkhq/sdk), [Ruby](https://github.com/tkhq/ruby-sdk)), we do not yet offer a full SDK for Python.
Python SDK for interacting with the Turnkey API.

If you are working on a project in Python and would benefit from a Python SDK please open an issue or get in touch with us (hello@turnkey.com) and we can discuss prioritizing this.
## 📦 Packages

## Stamper
This is a monorepo containing multiple packages:

The stamper utility stamps requests to the Turnkey API and authenticates the requests. In order to use the stamper to successfully make API calls you need to have a Turnkey organization and an associated API key that is authorized to make requests.
- **`turnkey-sdk-types`** - Pydantic type definitions for Turnkey API
- **`turnkey-http`** - HTTP client for making API requests
- **`turnkey-api-key-stamper`** - API key authentication stamper

Fill out the fields at the beginning of the python stamper script with the correct information.
## 🚀 Quick Start

### Installation

```bash
pip install turnkey-http turnkey-api-key-stamper
```

### Usage

```python
from turnkey_http import TurnkeyClient
from turnkey_api_key_stamper import ApiKeyStamper, ApiKeyStamperConfig

# Initialize stamper
config = ApiKeyStamperConfig(
api_public_key="your-api-public-key",
api_private_key="your-api-private-key"
)
stamper = ApiKeyStamper(config)

# Create client
client = TurnkeyClient(
base_url="https://api.turnkey.com",
stamper=stamper,
organization_id="your-org-id"
)

# Make API calls
response = client.get_whoami()
print(response)
```

## 💻 Development Setup

### Prerequisites

- Python 3.8+
- pip

### Setup

1. Clone the repository:
```bash
git clone https://github.com/tkhq/python-sdk.git
cd python-sdk
```

2. Create and activate virtual environment:
```bash
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
```

3. Install all packages in editable mode:
```bash
make install
```
ENDPOINT = "https://api.turnkey.com/public/v1/whoami"
API_PUBLIC_KEY="<Turnkey API Public Key (that starts with 02 or 03)>"
API_PRIVATE_KEY="<Turnkey API Private Key>"
ORG_ID = "<your org ID>"

This installs all packages with their dev dependencies in editable mode, so changes take effect immediately.


### Code Generation

This SDK uses code generation to stay in sync with the Turnkey API:

```bash
make generate # Generate both types and HTTP client
# or
make generate-types # Generate types only
make generate-http # Generate HTTP client only
```

### Testing

```bash
make test
```

### Code Quality

Before committing, run these commands to ensure code cleanliness:

```bash
make format # Format code with ruff
make typecheck # Check types with mypy
make test # Run tests
```

## 📝 Project Structure

```
python-sdk/
├── packages/
│ ├── sdk-types/ # Type definitions
│ │ ├── src/
│ │ └── scripts/ # Code generator
│ ├── http/ # HTTP client
│ │ ├── src/
│ │ ├── scripts/ # Code generator
│ │ └── tests/
│ └── api-key-stamper/ # Authentication
│ └── src/
├── schema/ # OpenAPI spec
└── examples/ # Example usage
```

26 changes: 26 additions & 0 deletions codegen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Codegen

Internal code generation scripts for the Turnkey Python SDK.

This directory contains utilities and scripts to generate:
- Type definitions from OpenAPI spec
- HTTP client from OpenAPI spec

## Usage

These scripts are called via the Makefile:

```bash
make generate # Generate all code
make generate-types # Generate type definitions only
make generate-http # Generate HTTP client only
```

## Structure

- `utils.py` - Shared utilities and constants
- `pydantic_helpers.py` - Helper functions for Pydantic model generation
- `generate_types.py` - Generates type definitions
- `generate_http.py` - Generates HTTP client

This is not a package and is not published to PyPI. It's only used during development.
45 changes: 45 additions & 0 deletions codegen/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""Constants for code generation from OpenAPI spec."""

# Code generation header
COMMENT_HEADER = "# @generated by codegen. DO NOT EDIT BY HAND"

# Activity type version mappings
VERSIONED_ACTIVITY_TYPES = {
"ACTIVITY_TYPE_CREATE_AUTHENTICATORS": "ACTIVITY_TYPE_CREATE_AUTHENTICATORS_V2",
"ACTIVITY_TYPE_CREATE_API_KEYS": "ACTIVITY_TYPE_CREATE_API_KEYS_V2",
"ACTIVITY_TYPE_CREATE_POLICY": "ACTIVITY_TYPE_CREATE_POLICY_V3",
"ACTIVITY_TYPE_CREATE_PRIVATE_KEYS": "ACTIVITY_TYPE_CREATE_PRIVATE_KEYS_V2",
"ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION": "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V7",
"ACTIVITY_TYPE_CREATE_USERS": "ACTIVITY_TYPE_CREATE_USERS_V3",
"ACTIVITY_TYPE_SIGN_RAW_PAYLOAD": "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2",
"ACTIVITY_TYPE_SIGN_TRANSACTION": "ACTIVITY_TYPE_SIGN_TRANSACTION_V2",
"ACTIVITY_TYPE_EMAIL_AUTH": "ACTIVITY_TYPE_EMAIL_AUTH_V3",
"ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION": "ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2",
"ACTIVITY_TYPE_UPDATE_POLICY": "ACTIVITY_TYPE_UPDATE_POLICY_V2",
"ACTIVITY_TYPE_INIT_OTP_AUTH": "ACTIVITY_TYPE_INIT_OTP_AUTH_V3",
"ACTIVITY_TYPE_INIT_OTP": "ACTIVITY_TYPE_INIT_OTP_V2",
"ACTIVITY_TYPE_INIT_USER_EMAIL_RECOVERY": "ACTIVITY_TYPE_INIT_USER_EMAIL_RECOVERY_V2",
}

# Methods that have only optional parameters
METHODS_WITH_ONLY_OPTIONAL_PARAMETERS = [
"getActivities",
"getApiKeys",
"getOrganization",
"getPolicies",
"getPrivateKeys",
"getSubOrgIds",
"getUsers",
"getWallets",
"getWhoami",
"listPrivateKeys",
"listUserTags",
]

# Terminal activity statuses
TERMINAL_ACTIVITY_STATUSES = [
"ACTIVITY_STATUS_COMPLETED",
"ACTIVITY_STATUS_FAILED",
"ACTIVITY_STATUS_CONSENSUS_NEEDED",
"ACTIVITY_STATUS_REJECTED",
]
Loading