Metadata-Version: 2.4
Name: sonic-sdk
Version: 0.3.0
Summary: Python SDK for the Sonic settlement engine — typed client for multi-currency payments with cryptographic receipts.
Author-email: Tower Technologies <dev@towerai.dev>
License: Apache-2.0
Project-URL: Homepage, https://github.com/ToweraiDev/sonic-pay
Project-URL: Repository, https://github.com/ToweraiDev/sonic-pay
Project-URL: Documentation, https://github.com/ToweraiDev/sonic-pay#readme
Keywords: sonic,settlement,payments,fintech,receipts,smartblocks,sbn
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic>=2.5
Requires-Dist: sbn-sdk>=0.6.0
Provides-Extra: engine
Requires-Dist: cryptography>=42.0; extra == "engine"
Requires-Dist: pydantic-settings>=2.1; extra == "engine"
Provides-Extra: db
Requires-Dist: sonic-sdk[engine]; extra == "db"
Requires-Dist: sqlalchemy[asyncio]>=2.0.0; extra == "db"
Requires-Dist: asyncpg>=0.29.0; extra == "db"
Requires-Dist: alembic>=1.13.0; extra == "db"
Provides-Extra: redis
Requires-Dist: redis>=5.0.0; extra == "redis"
Provides-Extra: server
Requires-Dist: sonic-sdk[db,engine,redis]; extra == "server"
Requires-Dist: pydantic[email]>=2.5; extra == "server"
Requires-Dist: fastapi>=0.109; extra == "server"
Requires-Dist: uvicorn[standard]>=0.27; extra == "server"
Requires-Dist: psycopg2-binary>=2.9; extra == "server"
Requires-Dist: python-jose[cryptography]>=3.3; extra == "server"
Requires-Dist: PyJWT>=2.7; extra == "server"
Requires-Dist: argon2-cffi>=23.1; extra == "server"
Requires-Dist: python-json-logger>=3.0; extra == "server"
Requires-Dist: prometheus-client>=0.20; extra == "server"
Requires-Dist: sentry-sdk[fastapi]>=2.0; extra == "server"
Provides-Extra: dev
Requires-Dist: sonic-sdk[server]; extra == "dev"
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
Requires-Dist: pytest-cov>=4.1; extra == "dev"
Requires-Dist: ruff>=0.2; extra == "dev"
Requires-Dist: mypy>=1.8; extra == "dev"
Requires-Dist: python-dotenv>=1.0.0; extra == "dev"
Provides-Extra: loadtest
Requires-Dist: locust>=2.24; extra == "loadtest"
Requires-Dist: httpx>=0.27.0; extra == "loadtest"

# Sonic SDK

Multi-currency settlement engine with cryptographic receipt attestation.

Sonic processes payments across rails (Stripe, Moov, Circle/USDC), normalizes through a treasury layer, executes payouts, and produces hash-chained receipts optionally attested by the [SmartBlocks Network](https://github.com/ToweraiDev/smartblocks_v2).

**You need a Sonic API key to use this SDK.** [Request access](mailto:dev@towerai.dev)

## Install

```bash
pip install sonic-sdk
```

## Quick Start

```python
from sonic.client import SonicClient

sonic = SonicClient(
    base_url="https://api.sonic.tower.dev",
    api_key="sonic_live_...",
)

# Create a payment
payment = sonic.create_payment(
    amount="250.00",
    currency="USD",
    rail="stripe_card",
    idempotency_key="inv-20260219-001",
)
print(payment.tx_id)        # "txn_a1b2c3..."
print(payment.receipt_hash)  # "sha256:..."

# Check transaction state
tx = sonic.get_transaction(payment.tx_id)
print(tx.state)              # "receivable_detected"
print(tx.inbound_amount)     # Decimal("250.00")

# Get finality info
finality = sonic.get_transaction_finality(payment.tx_id)
print(finality.finality_status)       # "final" | "confirmed" | "pending"
print(finality.hold_period_seconds)   # 0 for cards, 259200 for ACH

# Execute payout once cleared
payout = sonic.execute_payout(
    tx_id=payment.tx_id,
    recipient_id="rcpt_merchant_wallet",
    idempotency_key="payout-20260219-001",
)
print(payout.payout_status)  # "payout_executed"
print(payout.provider_ref)   # "po_stripe_xyz..."

# Verify receipt chain integrity
verification = sonic.verify_receipt(payment.tx_id, sequence=0)
print(verification.chain_valid)   # True
print(verification.sbn_attested)  # True (if SBN attestation completed)

# Public verification (no auth required — shareable with auditors)
public = sonic.public_verify(payment.receipt_hash)
print(public.chain_valid)
```

## Async

```python
from sonic.client import AsyncSonicClient

async with AsyncSonicClient(base_url="...", api_key="...") as sonic:
    payment = await sonic.create_payment(
        amount="100.00", currency="USD", idempotency_key="inv-001"
    )
    tx = await sonic.get_transaction(payment.tx_id)
```

## API Coverage

| Method | Endpoint | Returns |
|--------|----------|---------|
| `create_payment()` | `POST /v1/payments` | `PaymentResponse` |
| `execute_payout()` | `POST /v1/payouts` | `PayoutResponse` |
| `get_transaction()` | `GET /v1/transactions/{tx_id}` | `TransactionResponse` |
| `list_transactions()` | `GET /v1/transactions` | `TransactionListResponse` |
| `get_transaction_events()` | `GET /v1/transactions/{tx_id}/events` | `list[EventResponse]` |
| `get_transaction_finality()` | `GET /v1/transactions/{tx_id}/finality` | `FinalityResponse` |
| `get_receipts()` | `GET /v1/receipts/{tx_id}` | `list[ReceiptResponse]` |
| `verify_receipt()` | `GET /v1/receipts/{tx_id}/verify` | `VerifyResponse` |
| `public_verify()` | `GET /v1/verify/{hash}` | `VerifyResponse` |
| `get_merchant()` | `GET /v1/merchants/{id}` | `MerchantResponse` |
| `register_webhook()` | `POST /v1/merchants/{id}/webhooks` | `WebhookResponse` |

All response types are Pydantic v2 models with full type hints.

## Error Handling

```python
from sonic.client import SonicClient, SonicNotFound, SonicAuthError, SonicConflict

sonic = SonicClient(base_url="...", api_key="...")

try:
    tx = sonic.get_transaction("txn_nonexistent")
except SonicNotFound:
    print("Transaction not found")
except SonicAuthError:
    print("Bad API key")
except SonicConflict:
    print("State conflict (e.g., payout on uncleared tx)")
```

## Install Extras

```bash
pip install sonic-sdk              # Client only — all you need to call the API
pip install sonic-sdk[engine]      # + settlement engine, receipt builder, finality gate
pip install sonic-sdk[server]      # + FastAPI server, DB, Redis (run your own Sonic)
pip install sonic-sdk[dev]         # + pytest, ruff, mypy
```

## Supported Rails

| Rail | Provider | Finality | Reversible Window |
|------|----------|----------|-------------------|
| `stripe_card` | Stripe | Instant on capture | 120 days (chargeback) |
| `stripe_ach` | Stripe | 4 days | 60 days (ACH return) |
| `moov_ach` | Moov | 3 days | 60 days |
| `circle_usdc` | Circle | ~2 min (6 confirmations) | Irreversible |
| `circle_usdc_solana` | Circle | ~30s (32 confirmations) | Irreversible |

## License

Apache 2.0 — Tower Technologies, Brooks Holdings Inc.
