# boxtime

Cointime economics framework implementation for the Ergo blockchain.

## Description

Boxtime is a Python library that implements the [Cointime Economics](https://insights.glassnode.com/introducing-cointime-economics/) framework for Ergo. It reads pre-computed coinblocks created, destroyed, and stored — plus daily ERG/USD prices — from a database populated by the boxtime indexer.

Two connection paths are supported:

1. **Default (Supabase)** — uses the hosted Supabase project via PostgREST with an embedded publishable API key. No setup needed.
2. **Custom (Postgres)** — connect directly to your own Postgres instance via `asyncpg`.

## Installation

```bash
pip install boxtime
```

## Prerequisites

- **Python 3.10+**

## Quickstart

### Default (Supabase — no setup needed)

```python
from boxtime import Cointime

ct = Cointime()  # uses the hosted Supabase database

# Coinblocks created at a single height (= circulating supply in nanoERGs)
cbc = ct.coinblocks_created(500_000)

# Coinblocks destroyed at a single height
cbd = ct.coinblocks_destroyed(500_000)

# Coinblocks stored (CBC - CBD)
cbs = ct.coinblocks_stored(500_000)

# Totals over a range
total_cbc = ct.total_coinblocks_created(500_000, 500_100)
total_cbd = ct.total_coinblocks_destroyed(500_000, 500_100)
total_cbs = ct.total_coinblocks_stored(500_000, 500_100)
```

### Custom Postgres

```python
ct = Cointime(database_url="postgresql://user:pass@localhost:5432/boxtime")
cbc = ct.coinblocks_created(500_000)
```

### Price data

```python
import datetime

ct = Cointime()

# Daily ERG/USD price
price = ct.get_price(datetime.date(2024, 6, 15))

# Price range
prices = ct.get_price_range(datetime.date(2024, 1, 1), datetime.date(2024, 12, 31))
for date, usd in prices:
    print(date, usd)
```

### Price-enriched data (for plotting)

```python
# One CointimeDataPoint per day — last height of each day with daily price
data_points = ct.get_coinblocks_created(500_000, 510_000)
for dp in data_points:
    print(dp.height, dp.timestamp, dp.value, dp.price)

# Clean up when done
ct.close()
```

Each `CointimeDataPoint` bundles `height`, `timestamp`, `value` (cointime metric), and `price` (ERG/USD). Results are grouped by day using the last block height of each day.

## API Overview

### `Cointime(database_url=None, *, supabase_url=..., supabase_key=...)`

| Parameter | Default | Description |
| --- | --- | --- |
| `database_url` | `None` | If set, use direct Postgres via asyncpg |
| `supabase_url` | Hosted URL | Supabase project URL (default path) |
| `supabase_key` | Publishable key | Supabase API key (safe to embed) |

**Primitive metrics** (single height):
- `coinblocks_created(height)` — circulating supply at height
- `coinblocks_destroyed(height)` — sum of `input.value × lifespan` for all inputs
- `coinblocks_stored(height)` — CBC − CBD

**Aggregate metrics** (height range, inclusive):
- `total_coinblocks_created(start_height, end_height)`
- `total_coinblocks_destroyed(start_height, end_height)`
- `total_coinblocks_stored(start_height, end_height)`

**Price methods**:
- `get_price(date)` — daily ERG/USD price (`datetime.date`)
- `get_price_range(start_date, end_date)` — `List[Tuple[date, float]]`

**Convenience methods** (one `CointimeDataPoint` per day):
- `get_coinblocks_created(start_height, end_height)` — `List[CointimeDataPoint]`
- `get_coinblocks_destroyed(start_height, end_height)` — `List[CointimeDataPoint]`
- `get_coinblocks_stored(start_height, end_height)` — `List[CointimeDataPoint]`

**Utility**:
- `get_max_height()` — check data freshness
- `close()` — clean up connection pool / client

## Development

```bash
# Install with test dependencies
pip install -e ".[test]"

# Run tests
pytest
```

## License

This project is licensed under the [MIT License](LICENSE).
