Metadata-Version: 2.5
Name: olive-solana-sdk
Version: 0.1.0
Summary: Async Python SDK for market makers quoting Olive Solana options
Project-URL: Documentation, https://olive.ag/docs
Project-URL: Repository, https://github.com/macols77/olive
Project-URL: Issues, https://github.com/macols77/olive/issues
Author: Olive
License-Expression: MIT
License-File: LICENSE
Keywords: market-maker,olive,options,rfq,solana
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: jsonschema<5,>=4.23
Requires-Dist: solders<1,>=0.26
Requires-Dist: websockets<18,>=15
Provides-Extra: dev
Requires-Dist: build<2,>=1.2; extra == 'dev'
Requires-Dist: mypy<2,>=1.15; extra == 'dev'
Requires-Dist: psycopg[binary,pool]<4,>=3.2; extra == 'dev'
Requires-Dist: pytest-asyncio<2,>=0.25; extra == 'dev'
Requires-Dist: pytest<10,>=8.3; extra == 'dev'
Requires-Dist: ruff<1,>=0.11; extra == 'dev'
Requires-Dist: types-jsonschema<5,>=4.23; extra == 'dev'
Provides-Extra: postgres
Requires-Dist: psycopg[binary,pool]<4,>=3.2; extra == 'postgres'
Description-Content-Type: text/markdown

# Olive Solana Python SDK

The supported async Python client for market makers quoting Olive Solana options.
It implements only the native `/maker/v1/ws` protocol—there is no EVM or legacy
compatibility layer.

`ManagedMaker` is the recommended API. Maker code supplies entry premium or exit
amount and funding source; the SDK validates requests, binds canonical quote
fields, allocates durable quote IDs and nonces, signs through a local/HSM callback,
persists before submission, reconnects, and durably routes lifecycle events.

## Install

```bash
# From this repository:
pip install -e "packages/python-sdk[postgres]"

# After the distribution is published:
pip install "olive-solana-sdk[postgres]"
```

Python 3.11 or newer is required. Apply the packaged
`schemas/postgres-maker-store-v1.sql` with the maker's migration role and use
`schema_mode="verify"` in production. The default migration mode is intended for
development. `InMemoryMakerStore` is test-only.

The exact migration is also available programmatically with
`postgres_maker_store_schema()` so deployment tooling does not need to locate
the installed wheel's data directory.

## Managed maker quickstart

```python
import asyncio
import os

from olive_solana import (
    DeploymentIdentity,
    LocalKeypairMakerSigner,
    ManagedMaker,
    ManagedMakerEventHandlers,
    ManagedMakerOptions,
    PostgresMakerStore,
)


async def main() -> None:
    signer = LocalKeypairMakerSigner.from_json_file(
        os.environ["OLIVE_QUOTE_SIGNER_KEYPAIR"]
    )
    store = PostgresMakerStore(
        os.environ["DATABASE_URL"], schema_mode="verify"
    )

    async def entry(rfq):
        premium = await price_entry(rfq.request)
        return (
            rfq.decline("outside_risk_limits")
            if premium is None
            else rfq.quote(premium_usdc=premium)
        )

    async def exit_(rfq):
        amount = await price_exit(rfq.request)
        return (
            rfq.decline("outside_risk_limits")
            if amount is None
            else rfq.quote(
                exit_amount_usdc=amount,
                usdc_source=os.environ["OLIVE_EXIT_USDC_SOURCE"],
            )
        )

    maker = ManagedMaker(
        ManagedMakerOptions(
            url=os.environ["OLIVE_MAKER_WS_URL"],
            maker_config=os.environ["OLIVE_MAKER_CONFIG"],
            expected_deployment=DeploymentIdentity(
                program_id=os.environ["OLIVE_PROGRAM_ID"],
                genesis_hash=os.environ["OLIVE_GENESIS_HASH"],
                chain_tag=os.environ["OLIVE_CHAIN_TAG"],
            ),
            signer=signer,
            store=store,
            topics=("btc", "sol"),
            products=(0, 1),
            on_entry_rfq=entry,
            on_exit_rfq=exit_,
            events=ManagedMakerEventHandlers(
                # Selection is feedback, not execution.
                on_entry_selected=record_selection,
                # Only finalized fills trigger hedging/reconciliation.
                on_entry_filled=hedge_finalized_entry,
                on_exit_filled=reconcile_finalized_exit,
                on_funding_required=alert_funding,
                on_default=page_risk,
                on_settlement=record_settlement,
            ),
        )
    )
    try:
        await maker.run()
    finally:
        await store.close()


asyncio.run(main())
```

An empty topic or product collection subscribes to everything authorized by
`maker.hello`. Keep `takeover_existing_session=False` for ordinary starts; enable
it only for an intentional failover.

## Operational preflight

The doctor authenticates without subscribing, taking over a live maker, or
submitting quotes:

```bash
olive-maker-doctor --topics btc,sol --products 0,1 \
  --exit-sources "$OLIVE_EXIT_USDC_SOURCE"

olive-maker-doctor --json > maker-doctor.json
```

Connection and deployment values default from `OLIVE_MAKER_WS_URL`,
`OLIVE_MAKER_CONFIG`, `OLIVE_PROGRAM_ID`, `OLIVE_GENESIS_HASH`,
`OLIVE_CHAIN_TAG`, and `OLIVE_QUOTE_SIGNER_KEYPAIR`.

## Reliability contract

- Wire integers remain canonical decimal strings.
- Entry and exit nonce namespaces are separate.
- Complete quote, digest, and signature are committed before submission.
- Restart retries only the exact stored quote and signature.
- Durable events are stored before `event.ack`; local handler completion is
  persisted independently.
- `quote.selected` and `exit_quote.selected` are not fills. Only finalized
  `trade.filled` and `exit.filled` are canonical execution signals.
- Signatures and private signer data are never included in SDK status events.

The low-level `MakerWsClient` remains available for makers requiring custom
orchestration. Releases must pass the shared fixture/digest suite and all
fail-closed maker conformance scenarios.

## Development

```bash
python -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/ruff check .
.venv/bin/mypy src
.venv/bin/pytest
.venv/bin/python -m build
```

## Release

PyPI releases use trusted publishing from
`.github/workflows/publish-python-sdk.yml`; no long-lived API token is stored in
GitHub. Configure the PyPI publisher for repository `macols77/olive`, workflow
`publish-python-sdk.yml`, and environment `pypi`. Pushing a tag that exactly
matches `python-sdk-v<pyproject version>` builds, checks, and uploads both the
wheel and source distribution. Protect the `pypi` environment with required
reviewer approval.
