# Talarion SDK

Python client for the [Talarion](https://talarion.tech) prediction market maker API.

## Installation

```bash
pip install talarion
```

For EOA (externally owned account) direct on-chain interaction:

```bash
pip install talarion[eoa]
```

## Quick Start

```python
import asyncio
from datetime import datetime, timezone, timedelta
from talarion import TalarionClient

async def main():
    async with TalarionClient(api_key="tlrn_...") as client:
        # Generate a prediction market
        instrument = await client.generate_instrument(
            query="Will BTC hit 100k?",
            resolution_time=datetime.now(timezone.utc) + timedelta(days=7),
        )

        # Get a price quote
        quote = await client.get_quote(
            instrument.instrument_id,
            buy_yes=True,
            amount=10.0,
            user_id="user-123",
        )
        print(f"Price: {quote.price}, Amount: {quote.amount}")

        # Submit an order (returns EIP-712 data to sign)
        result = await client.submit_order(
            instrument_id=instrument.instrument_id,
            user_id="user-123",
            caller_address="0xYourSafeAddress",
            amount=quote.amount,
            price=quote.price,
            buy_yes=True,
        )

        # Sign each operation's EIP-712 data with your wallet,
        # then relay the signed operations
        signatures = {}  # {operation_id: "0xSignature..."}
        for op in result.operation_sequence.operations:
            sig = sign_eip712(op.eip_712_tx)  # your signing logic
            signatures[op.operation_id] = sig

        relay = await client.relay(
            result.operation_sequence.sequence_id,
            signatures,
        )
        print(f"Relay successful: {relay.successful}")

asyncio.run(main())
```

## EOA Direct Interaction

For EOA wallets that want to interact with the Escrow contract directly
(bypassing the Safe/relay flow):

```python
from talarion.eoa import (
    build_approve_usdc_tx,
    build_create_trade_tx,
    sign_and_send,
)

ESCROW = "0xEscrowContractAddress"
USDC = "0xUsdcContractAddress"
RPC = "https://tenderly.rpc.polygon.community/"
PK = "0xYourPrivateKey"

# 1. Approve USDC spending (one-time)
approve_tx = build_approve_usdc_tx(USDC, ESCROW)
sign_and_send(approve_tx, PK, RPC)

# 2. After calling client.submit_order(), build and send the trade tx
result = ...  # from client.submit_order()
trade_tx = build_create_trade_tx(result, ESCROW)
tx_hash = sign_and_send(trade_tx, PK, RPC)
print(f"Trade created: {tx_hash}")
```

## API Reference

### Client Methods

| Method | Description |
|--------|-------------|
| `generate_instrument(query, resolution_time)` | Create a new prediction market |
| `get_instrument(instrument_id)` | Fetch instrument details |
| `get_settlement(instrument_id)` | Get settlement value (0-1) |
| `get_quote(instrument_id, buy_yes, *, amount, dollars, user_id)` | Request a price quote |
| `submit_order(instrument_id, user_id, caller_address, amount, price, buy_yes)` | Submit a trade order |
| `cancel_order(trade_id, caller_address)` | Cancel a pending trade |
| `relay(sequence_id, signatures)` | Relay signed operations on-chain |
| `get_trade(trade_id)` | Fetch a single trade |
| `list_trades(*, status, user_id, instrument_id)` | List trades with filters |
| `get_user_trades(user_id, *, status)` | List a user's trades |
| `get_user_pnl(user_id)` | Get user's realized P&L |

### EOA Functions

| Function | Description |
|----------|-------------|
| `build_create_trade_tx(result, escrow_address)` | Build unsigned `createTrade` tx |
| `build_cancel_trade_tx(trade_id, escrow_address)` | Build unsigned `cancelPendingTrade` tx |
| `build_approve_usdc_tx(usdc_address, escrow_address)` | Build unsigned USDC approval tx |
| `sign_and_send(tx, private_key, rpc_url)` | Sign and broadcast a transaction |

### Exceptions

| Exception | HTTP Status | Description |
|-----------|-------------|-------------|
| `TalarionError` | any | Base exception |
| `AuthenticationError` | 401 | Invalid or missing API key |
| `ValidationError` | 400 | Invalid request parameters |
| `NotFoundError` | 404 | Resource not found |
| `ConflictError` | 409 | Duplicate order or already relayed |
| `QuoteProcessingError` | 202 | Quote still being generated |
| `ServerError` | 5xx | Server-side error |

## License

MIT
