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
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ repos:
additional_dependencies: ["openai>=3.7.0", "httpx2>=2.12.0", "x402>=2.21.0"]
args: [--strict, --config-file=pyproject.toml]
pass_filenames: false
entry: mypy src/qntx/openai
entry: mypy src/x402_openai

ci:
autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks
Expand Down
2 changes: 1 addition & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ format:

# Run the mypy type checker.
typecheck:
uv run mypy src/qntx/openai
uv run mypy src/x402_openai

# Run pytest.
test:
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ format: ## Run ruff formatter (auto-fix)
uv run ruff format .

typecheck: ## Run mypy type checker
uv run mypy src/qntx/openai
uv run mypy src/x402_openai

test: ## Run pytest
uv run pytest
Expand Down
28 changes: 13 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

<div align="center">

# qntx-openai
# x402-openai

**Drop-in OpenAI Python client with transparent [x402](https://www.x402.org/) payment support.**

[![PyPI](https://img.shields.io/pypi/v/qntx-openai)](https://pypi.org/project/qntx-openai/)
[![PyPI](https://img.shields.io/pypi/v/x402-openai)](https://pypi.org/project/x402-openai/)
[![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue)](https://python.org)
[![CI](https://github.com/qntx/openai-python/actions/workflows/python.yml/badge.svg)](https://github.com/qntx/openai-python/actions)
[![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
Expand All @@ -23,18 +23,16 @@ Supplying `evm` registers both **`exact` and `upto`**. `svm` and `tvm` register
## Installation

```bash
pip install 'qntx-openai[evm]' # EVM (Ethereum / Base / …)
pip install 'qntx-openai[svm]' # Solana
pip install 'qntx-openai[tvm]' # TVM (TON)
pip install 'qntx-openai[all]' # all chains
pip install 'x402-openai[evm]' # EVM (Ethereum / Base / …)
pip install 'x402-openai[svm]' # Solana
pip install 'x402-openai[tvm]' # TVM (TON)
pip install 'x402-openai[all]' # all chains
```

The PyPI name `x402-openai` is abandoned. Install `qntx-openai`.

## Quick Start

```python
from qntx.openai import X402OpenAI
from x402_openai import X402OpenAI

client = X402OpenAI(evm="0x…")

Expand All @@ -52,7 +50,7 @@ Pass `svm="base58…"` instead of `evm` to pay on Solana — the rest of the API
### Streaming

```python
from qntx.openai import AsyncX402OpenAI
from x402_openai import AsyncX402OpenAI

client = AsyncX402OpenAI(evm="0x…")

Expand Down Expand Up @@ -124,7 +122,7 @@ client = X402OpenAI(
- **SVM `exact`:** the 402 must include `extra.feePayer`. There is no SVM `upto` scheme in Python `x402`.

```python
from qntx.openai import X402OpenAI, prefer_scheme
from x402_openai import X402OpenAI, prefer_scheme

client = X402OpenAI(
evm="0x…",
Expand All @@ -139,7 +137,7 @@ client = X402OpenAI(
Use policies to prefer a chain or scheme when multiple options remain after spend controls. Policies do not cap spend.

```python
from qntx.openai import X402OpenAI, prefer_network, prefer_scheme
from x402_openai import X402OpenAI, prefer_network, prefer_scheme

client = X402OpenAI(
evm="0x…",
Expand Down Expand Up @@ -194,9 +192,9 @@ All standard OpenAI options (`base_url`, `timeout`, `max_retries`, …) are forw

| Option | Chain | Install extra |
| :----- | :---- | :------------ |
| `evm` | EVM | `qntx-openai[evm]` |
| `svm` | Solana | `qntx-openai[svm]` |
| `tvm` | TVM | `qntx-openai[tvm]` |
| `evm` | EVM | `x402-openai[evm]` |
| `svm` | Solana | `x402-openai[svm]` |
| `tvm` | TVM | `x402-openai[tvm]` |

## Examples

Expand Down
2 changes: 1 addition & 1 deletion examples/chat_evm.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import os

from qntx.openai import X402OpenAI
from x402_openai import X402OpenAI

client = X402OpenAI(evm=os.environ["EVM_PRIVATE_KEY"])

Expand Down
2 changes: 1 addition & 1 deletion examples/chat_evm_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import os

from qntx.openai import X402OpenAI, prefer_network, prefer_scheme
from x402_openai import X402OpenAI, prefer_network, prefer_scheme

client = X402OpenAI(
evm=os.environ["EVM_PRIVATE_KEY"],
Expand Down
2 changes: 1 addition & 1 deletion examples/chat_multichain_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

import os

from qntx.openai import X402OpenAI, prefer_network, prefer_scheme
from x402_openai import X402OpenAI, prefer_network, prefer_scheme

client = X402OpenAI(
evm=os.environ["EVM_PRIVATE_KEY"],
Expand Down
2 changes: 1 addition & 1 deletion examples/chat_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import os

from qntx.openai import X402OpenAI, prefer_network, prefer_scheme
from x402_openai import X402OpenAI, prefer_network, prefer_scheme

client = X402OpenAI(
evm=os.environ["EVM_PRIVATE_KEY"],
Expand Down
2 changes: 1 addition & 1 deletion examples/chat_svm.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import os

from qntx.openai import X402OpenAI
from x402_openai import X402OpenAI

client = X402OpenAI(svm=os.environ["SOLANA_PRIVATE_KEY"])

Expand Down
2 changes: 1 addition & 1 deletion examples/chat_tvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import os

from qntx.openai import X402OpenAI
from x402_openai import X402OpenAI

client = X402OpenAI(tvm=os.environ["TVM_PRIVATE_KEY"])
try:
Expand Down
2 changes: 1 addition & 1 deletion examples/chat_upto.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import os

from qntx.openai import X402OpenAI, prefer_scheme
from x402_openai import X402OpenAI, prefer_scheme

client = X402OpenAI(
evm=os.environ["EVM_PRIVATE_KEY"],
Expand Down
2 changes: 1 addition & 1 deletion examples/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import os

from qntx.openai import X402OpenAI
from x402_openai import X402OpenAI

client = X402OpenAI(evm=os.environ["EVM_PRIVATE_KEY"])

Expand Down
2 changes: 1 addition & 1 deletion examples/streaming_evm.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import asyncio
import os

from qntx.openai import AsyncX402OpenAI
from x402_openai import AsyncX402OpenAI


async def main() -> None:
Expand Down
2 changes: 1 addition & 1 deletion examples/streaming_evm_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import asyncio
import os

from qntx.openai import AsyncX402OpenAI, prefer_network, prefer_scheme
from x402_openai import AsyncX402OpenAI, prefer_network, prefer_scheme


async def main() -> None:
Expand Down
2 changes: 1 addition & 1 deletion examples/streaming_svm.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import asyncio
import os

from qntx.openai import AsyncX402OpenAI
from x402_openai import AsyncX402OpenAI


async def main() -> None:
Expand Down
14 changes: 6 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "qntx-openai"
name = "x402-openai"
version = "1.0.0"
description = "Drop-in OpenAI Python client with transparent x402 payment support."
readme = "README.md"
Expand Down Expand Up @@ -43,9 +43,9 @@ tvm = [
"x402[tvm]>=2.21.0",
]
all = [
"qntx-openai[evm]",
"qntx-openai[svm]",
"qntx-openai[tvm]",
"x402-openai[evm]",
"x402-openai[svm]",
"x402-openai[tvm]",
]
dev = [
"pytest>=8.0",
Expand All @@ -62,7 +62,7 @@ Repository = "https://github.com/qntx/openai-python"
Issues = "https://github.com/qntx/openai-python/issues"

[tool.hatch.build.targets.wheel]
packages = ["src/qntx"]
packages = ["src/x402_openai"]

[tool.ruff]
target-version = "py312"
Expand All @@ -87,15 +87,13 @@ ignore = [
]

[tool.ruff.lint.isort]
known-first-party = ["qntx"]
known-first-party = ["x402_openai"]

[tool.mypy]
python_version = "3.12"
strict = true
warn_return_any = true
warn_unused_configs = true
namespace_packages = true
explicit_package_bases = true
mypy_path = "src"

[[tool.mypy.overrides]]
Expand Down
10 changes: 5 additions & 5 deletions src/qntx/openai/__init__.py → src/x402_openai/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""qntx-openai — Drop-in OpenAI client with transparent x402 payment.
"""x402-openai — Drop-in OpenAI client with transparent x402 payment.

Quick start::

from qntx.openai import prefer_scheme, X402OpenAI
from x402_openai import prefer_scheme, X402OpenAI

client = X402OpenAI(evm="0x…")

Expand All @@ -24,9 +24,9 @@

from x402 import SpendControls, x402Client, x402ClientSync

from qntx.openai._chains._types import EvmConfig, SvmConfig, TvmConfig
from qntx.openai._client import AsyncX402OpenAI, X402OpenAI
from qntx.openai._policies import prefer_network, prefer_scheme
from x402_openai._chains._types import EvmConfig, SvmConfig, TvmConfig
from x402_openai._client import AsyncX402OpenAI, X402OpenAI
from x402_openai._policies import prefer_network, prefer_scheme

__all__ = [
"AsyncX402OpenAI",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from __future__ import annotations

from qntx.openai._chains._register import ChainHandles, register_chains
from qntx.openai._chains._types import EvmConfig, SvmConfig, TvmConfig
from x402_openai._chains._register import ChainHandles, register_chains
from x402_openai._chains._types import EvmConfig, SvmConfig, TvmConfig

__all__ = ["ChainHandles", "EvmConfig", "SvmConfig", "TvmConfig", "register_chains"]
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
if TYPE_CHECKING:
from x402 import x402Client, x402ClientSync

from qntx.openai._chains._types import EvmConfig
from x402_openai._chains._types import EvmConfig


def register_evm(client: x402Client | x402ClientSync, config: EvmConfig) -> None:
Expand All @@ -17,7 +17,7 @@ def register_evm(client: x402Client | x402ClientSync, config: EvmConfig) -> None
from x402.mechanisms.evm.upto import UptoEvmScheme
except ImportError as e:
raise ImportError(
"EVM key provided but x402[evm] is not installed. pip install 'qntx-openai[evm]'"
"EVM key provided but x402[evm] is not installed. pip install 'x402-openai[evm]'"
) from e

account = Account.from_key(config.private_key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@

from typing import TYPE_CHECKING

from qntx.openai._chains._evm import register_evm
from qntx.openai._chains._svm import register_svm
from qntx.openai._chains._tvm import register_tvm
from qntx.openai._chains._types import EvmConfig, SvmConfig, TvmConfig
from x402_openai._chains._evm import register_evm
from x402_openai._chains._svm import register_svm
from x402_openai._chains._tvm import register_tvm
from x402_openai._chains._types import EvmConfig, SvmConfig, TvmConfig

if TYPE_CHECKING:
from x402 import x402Client, x402ClientSync

from qntx.openai._chains._tvm import _TvmScheme
from qntx.openai._payments import PaymentSourceOptions
from x402_openai._chains._tvm import _TvmScheme
from x402_openai._payments import PaymentSourceOptions


class ChainHandles:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
if TYPE_CHECKING:
from x402 import x402Client, x402ClientSync

from qntx.openai._chains._types import SvmConfig
from x402_openai._chains._types import SvmConfig


def register_svm(client: x402Client | x402ClientSync, config: SvmConfig) -> None:
Expand All @@ -16,7 +16,7 @@ def register_svm(client: x402Client | x402ClientSync, config: SvmConfig) -> None
from x402.mechanisms.svm.exact import ExactSvmScheme
except ImportError as e:
raise ImportError(
"SVM key provided but x402[svm] is not installed. pip install 'qntx-openai[svm]'"
"SVM key provided but x402[svm] is not installed. pip install 'x402-openai[svm]'"
) from e

signer = KeypairSigner.from_base58(config.private_key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
if TYPE_CHECKING:
from x402 import x402Client, x402ClientSync

from qntx.openai._chains._types import TvmConfig
from x402_openai._chains._types import TvmConfig


class _TvmScheme(Protocol):
Expand All @@ -24,7 +24,7 @@ def register_tvm(client: x402Client | x402ClientSync, config: TvmConfig) -> _Tvm
from x402.mechanisms.tvm.exact import ExactTvmScheme
except ImportError as e:
raise ImportError(
"TVM key provided but x402[tvm] is not installed. pip install 'qntx-openai[tvm]'"
"TVM key provided but x402[tvm] is not installed. pip install 'x402-openai[tvm]'"
) from e

network = config.network or TVM_MAINNET
Expand Down
File renamed without changes.
10 changes: 5 additions & 5 deletions src/qntx/openai/_client.py → src/x402_openai/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@
from typing import TYPE_CHECKING, Any, Literal, Self

import httpx2
from httpx2._utils import get_environment_proxies

import openai
from httpx2._utils import get_environment_proxies
from openai import DefaultAsyncHttpx2Client, DefaultHttpx2Client
from qntx.openai._payments import (

from x402_openai._payments import (
BuiltClient,
PaymentSourceOptions,
assert_payment_options,
build_x402_client,
)
from qntx.openai._transport import X402Httpx2AsyncTransport, X402Httpx2SyncTransport
from x402_openai._transport import X402Httpx2AsyncTransport, X402Httpx2SyncTransport

if TYPE_CHECKING:
from x402 import SpendControls, x402Client, x402ClientSync

from qntx.openai._chains._types import EvmConfig, SvmConfig, TvmConfig
from x402_openai._chains._types import EvmConfig, SvmConfig, TvmConfig

DEFAULT_BASE_URL = "https://llm.qntx.org/v1"
_REMOVED = ("wallet", "wallets", "mnemonic", "max_amount", "http_client")
Expand Down
Loading