Metadata-Version: 2.4
Name: neutrl-core
Version: 2.0.1
Summary: Core utilities for Neutrl Protocol services — config, logging, RPC management, and common helpers
Author-email: Daniel Mercer <mhoonumabaamercy@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/mhoonumabaamercy-hub/neutrl-core
Project-URL: Documentation, https://github.com/mhoonumabaamercy-hub/neutrl-core#readme
Project-URL: Repository, https://github.com/mhoonumabaamercy-hub/neutrl-core
Keywords: neutrl,defi,configuration,rpc,ethereum,utilities
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic>=2.0.0
Requires-Dist: pydantic-settings>=2.0.0
Requires-Dist: httpx>=0.24.0
Requires-Dist: structlog>=23.0.0
Provides-Extra: web3
Requires-Dist: web3>=6.0.0; extra == "web3"
Provides-Extra: nats
Requires-Dist: nats-py>=2.0.0; extra == "nats"
Provides-Extra: redis
Requires-Dist: redis>=5.0.0; extra == "redis"
Provides-Extra: all
Requires-Dist: web3>=6.0.0; extra == "all"
Requires-Dist: nats-py>=2.0.0; extra == "all"
Requires-Dist: redis>=5.0.0; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Dynamic: license-file

# neutrl-core

Core utilities for Neutrl Protocol services. Provides standardized configuration loading, structured logging, RPC provider management, and retry logic.

## Installation

```bash
pip install neutrl-core

# With optional extras:
pip install neutrl-core[web3]     # web3.py integration
pip install neutrl-core[nats]     # NATS messaging
pip install neutrl-core[redis]    # Redis support
pip install neutrl-core[all]      # Everything
```

## Quick Start

### Configuration

```python
from neutrl_core import NeutrlConfig

# Loads from environment variables (NEUTRL_* prefix) and .env file
config = NeutrlConfig()

print(config.env)             # Environment.DEVELOPMENT
print(config.db.dsn)          # postgresql://neutrl:@localhost:5432/neutrl
print(config.nats.url)        # nats://localhost:4222
print(config.hasura.url)      # http://localhost:8080/v1/graphql
print(config.is_production)   # False

# Per-chain RPC config
eth_config = config.get_chain(1)
print(eth_config.rpc_urls)    # ["https://eth.llamarpc.com"]
```

### Environment Variables

```env
# Core
NEUTRL_ENV=production
NEUTRL_SERVICE_NAME=trading-engine
NEUTRL_LOG_LEVEL=INFO
NEUTRL_LOG_FORMAT=json

# Chain RPC
NEUTRL_CHAIN_ETH_RPC_URLS=https://eth.llamarpc.com,https://rpc.ankr.com/eth
NEUTRL_CHAIN_ETH_CHAIN_ID=1

# Database
NEUTRL_DB_HOST=db.internal
NEUTRL_DB_PORT=5432
NEUTRL_DB_NAME=neutrl_prod
NEUTRL_DB_USER=app
NEUTRL_DB_PASSWORD=secret

# NATS
NEUTRL_NATS_URL=nats://nats.internal:4222
NEUTRL_NATS_TOKEN=nats-auth-token

# Redis
NEUTRL_REDIS_URL=redis://redis.internal:6379

# Hasura
NEUTRL_HASURA_URL=https://hasura.internal/v1/graphql
NEUTRL_HASURA_ADMIN_SECRET=hasura-secret
```

### Structured Logging

```python
from neutrl_core import setup_logging, get_logger

setup_logging(level="INFO", format="json", service_name="trading-engine")

log = get_logger("positions")
log.info("position_opened", symbol="ETH-PERP", size=1.5, leverage=3)
log.warning("margin_low", account="0xabc...", ratio=0.12)

# Output (JSON):
# {"event": "position_opened", "symbol": "ETH-PERP", "size": 1.5, ...}
```

### RPC Provider Management

```python
from neutrl_core import ProviderManager, RPCEndpoint

manager = ProviderManager([
    RPCEndpoint(url="https://eth.llamarpc.com", chain_id=1),
    RPCEndpoint(url="https://rpc.ankr.com/eth", chain_id=1),
    RPCEndpoint(url="https://arb1.arbitrum.io/rpc", chain_id=42161),
])

# Auto-routes to healthiest provider
block = manager.call(1, "eth_blockNumber")
print(f"Block: {int(block, 16)}")

# Health monitoring
for health in manager.health_report(chain_id=1):
    print(f"{health.endpoint.url}: {health.status.value} ({health.latency_ms:.0f}ms)")

# Async support
result = await manager.async_call(42161, "eth_getBalance", ["0xabc...", "latest"])
```

### Retry Logic

```python
from neutrl_core import RetryPolicy, retry, async_retry

@retry(RetryPolicy(max_attempts=5, base_delay=0.5))
def fetch_price(symbol: str) -> float:
    return external_api.get_price(symbol)

@async_retry(RetryPolicy(max_attempts=3, base_delay=1.0))
async def submit_order(params: dict) -> str:
    return await exchange.place_order(params)
```

## API Reference

### Configuration

| Class | Description |
|-------|-------------|
| `NeutrlConfig` | Root config — aggregates all sub-configs |
| `ChainConfig` | Per-chain RPC endpoints and settings |
| `DatabaseConfig` | PostgreSQL connection with DSN builder |
| `NATSConfig` | NATS messaging connection settings |
| `RedisConfig` | Redis with sentinel support |
| `HasuraConfig` | Hasura GraphQL endpoint and auth |

### Provider Management

| Class / Method | Description |
|---------------|-------------|
| `ProviderManager` | Multi-provider RPC client with failover |
| `RPCEndpoint` | Single endpoint configuration |
| `ProviderHealth` | Health stats with latency tracking |
| `.call()` / `.async_call()` | JSON-RPC with automatic failover |
| `.health_report()` | Provider health summary |

### Logging

| Function | Description |
|----------|-------------|
| `setup_logging()` | Configure structlog for a service |
| `get_logger()` | Get a bound structlog logger |
| `bind_context()` | Add context to all logs in scope |
| `clear_context()` | Reset context variables |

### Retry

| Class / Function | Description |
|-----------------|-------------|
| `RetryPolicy` | Configurable retry with exponential backoff |
| `@retry()` | Sync retry decorator |
| `@async_retry()` | Async retry decorator |

## Requirements

- Python 3.9+
- pydantic >= 2.0
- pydantic-settings >= 2.0
- httpx >= 0.24
- structlog >= 23.0

## License

MIT
