Metadata-Version: 2.4
Name: quidclaw-crypto
Version: 0.1.0
Summary: Cryptocurrency support for QuidClaw — on-chain and exchange sync
Project-URL: Homepage, https://github.com/ThorbJ/quidclaw-crypto
Project-URL: Repository, https://github.com/ThorbJ/quidclaw-crypto
Author: Yue Jiang
License-Expression: GPL-2.0-only
Keywords: beancount,blockchain,crypto,exchange,quidclaw
Classifier: Development Status :: 3 - Alpha
Classifier: License :: OSI Approved :: GNU General Public License v2 (GPLv2)
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Office/Business :: Financial :: Accounting
Requires-Python: <3.14,>=3.10
Requires-Dist: ccxt>=4.0
Requires-Dist: quidclaw>=0.4.0
Requires-Dist: requests>=2.28
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == 'dev'
Description-Content-Type: text/markdown

# quidclaw-crypto

Cryptocurrency plugin for [QuidClaw](https://github.com/ThorbJ/quidclaw) -- sync on-chain wallet data and centralized exchange balances/trades into your Beancount ledger.

## What It Does

QuidClaw is a local-first personal CFO powered by AI and Beancount. This plugin extends it with cryptocurrency support:

- **Exchange sync** -- pull trades, balances, deposits, and withdrawals from 100+ centralized exchanges via [CCXT](https://github.com/ccxt/ccxt)
- **On-chain sync** -- pull transaction history and ERC-20 token transfers from 7 EVM chains via the Etherscan V2 API
- **Agent Skill** -- AI workflow instructions that teach Claude how to set up crypto sources, sync data, and record Beancount transactions

Raw data is synced as JSON files. The AI (via the agent skill) interprets this data and records structured Beancount transactions using QuidClaw's `add-txn` command. The plugin itself never interprets financial data -- that separation is a core QuidClaw architectural constraint.

## Features

### Exchange Sync (CCXT)

Connects to centralized exchanges using read-only API keys. Syncs:

- **Trades** -- all executed trades across all markets, with incremental sync via `last_trade_timestamp`
- **Balances** -- current balance snapshot (total, free, used per asset)
- **Deposits** -- deposit history (if the exchange supports the `fetchDeposits` endpoint)
- **Withdrawals** -- withdrawal history (if the exchange supports `fetchWithdrawals`)

Supported exchanges include any exchange supported by CCXT (100+). Popular ones:

| Exchange | CCXT ID | Notes |
|----------|---------|-------|
| Binance | `binance` | Largest by volume |
| OKX | `okx` | Requires passphrase |
| Coinbase | `coinbase` | US-based |
| Kraken | `kraken` | EUR pairs |
| Bybit | `bybit` | Derivatives + spot |
| Gate.io | `gate` | Wide altcoin coverage |
| KuCoin | `kucoin` | Requires passphrase |
| Bitget | `bitget` | Copy trading |
| HTX (Huobi) | `htx` | Asia-focused |
| MEXC | `mexc` | Wide altcoin listing |

Full list: run `python -c "import ccxt; print('\n'.join(sorted(ccxt.exchanges)))"`.

### On-Chain Sync (EVM Explorer)

Connects to Etherscan-compatible block explorer APIs via the unified Etherscan V2 API. Syncs:

- **Normal transactions** -- native token transfers (ETH, BNB, MATIC, etc.) with gas fees, timestamps, and counterparty addresses
- **ERC-20 token transfers** -- all token movements to/from the wallet, including token name, symbol, decimals, and amount

Supported chains:

| Chain | CLI ID | Chain ID | Explorer |
|-------|--------|----------|----------|
| Ethereum | `ethereum` | 1 | etherscan.io |
| BSC (BNB Chain) | `bsc` | 56 | bscscan.com |
| Polygon | `polygon` | 137 | polygonscan.com |
| Arbitrum | `arbitrum` | 42161 | arbiscan.io |
| Optimism | `optimism` | 10 | optimistic.etherscan.io |
| Base | `base` | 8453 | basescan.org |
| Avalanche | `avalanche` | 43114 | snowtrace.io |

### Agent Skill

The plugin ships with an agent skill (`quidclaw-crypto`) that includes:

- **SKILL.md** -- main skill definition with available commands, sync flow, and data interpretation guidance
- **references/exchange-setup.md** -- API key creation guides for Binance, OKX, Coinbase, Kraken
- **references/chain-setup.md** -- supported chains, Etherscan API key setup, what data gets synced
- **references/accounting-model.md** -- Beancount account structure, commodity definitions, transaction examples

The skill is installed to `.claude/skills/` when you run `quidclaw upgrade`.

## Installation

```bash
pip install quidclaw-crypto
quidclaw upgrade    # copies the crypto agent skill to .claude/skills/
```

Requires:
- QuidClaw >= 0.4.0
- Python >= 3.10, < 3.14

## Usage

### Add an exchange source

```bash
# Binance (basic)
quidclaw crypto add-exchange my-binance \
  --exchange binance \
  --api-key $BINANCE_API_KEY \
  --secret $BINANCE_SECRET

# OKX (requires passphrase)
quidclaw crypto add-exchange my-okx \
  --exchange okx \
  --api-key $OKX_API_KEY \
  --secret $OKX_SECRET \
  --passphrase $OKX_PASSPHRASE
```

### Add an on-chain wallet

```bash
# Ethereum wallet
quidclaw crypto add-wallet my-eth \
  --address 0x1234...abcd \
  --chain ethereum \
  --api-key $ETHERSCAN_API_KEY

# BSC wallet (same Etherscan key works across chains)
quidclaw crypto add-wallet my-bsc \
  --address 0x1234...abcd \
  --chain bsc \
  --api-key $ETHERSCAN_API_KEY

# Without API key (works but rate-limited)
quidclaw crypto add-wallet my-arb \
  --address 0x5678...efgh \
  --chain arbitrum
```

### Sync data

```bash
quidclaw sync my-binance     # sync exchange trades, balances, deposits, withdrawals
quidclaw sync my-eth         # sync on-chain transactions and ERC-20 transfers
```

### View portfolio status

```bash
quidclaw crypto portfolio          # text output
quidclaw crypto portfolio --json   # JSON output
```

### List all configured sources

```bash
quidclaw list-sources   # shows all sources including crypto
```

## API Key Setup

### Exchange API Keys

Always create **read-only** API keys. QuidClaw only reads data -- it never places trades or initiates withdrawals.

For security, use environment variables instead of hardcoding keys:

```bash
export BINANCE_API_KEY="your-key-here"
export BINANCE_SECRET="your-secret-here"
```

See `src/quidclaw_crypto/skills/quidclaw-crypto/references/exchange-setup.md` for detailed per-exchange setup guides (Binance, OKX, Coinbase, Kraken).

### Etherscan API Key

1. Register at [etherscan.io](https://etherscan.io) (free account)
2. Go to API Keys > Add > copy the key

Free tier: 5 calls/second, 100,000 calls/day. A single key works across all supported chains via the V2 API.

See `src/quidclaw_crypto/skills/quidclaw-crypto/references/chain-setup.md` for details.

## Data Storage

Synced data is stored as raw JSON files under the QuidClaw data directory:

```
sources/
  my-binance/
    trades/           # one JSON file per sync, per market pair
    balances/         # one JSON file per sync (balance snapshot)
    deposits/         # one JSON file per sync
    withdrawals/      # one JSON file per sync
    state.yaml        # incremental sync state (last_trade_timestamp, last_sync, total_synced)
  my-eth/
    transactions/     # one JSON file per sync (normal transactions)
    erc20/            # one JSON file per sync (ERC-20 token transfers)
    state.yaml        # incremental sync state (last_block, last_sync, total_synced)
```

Files are named with UTC timestamps: `20260328T143022_BTC-USDT.json` (trades) or `20260328T143022.json` (balances, transactions).

## How It Works as a QuidClaw Plugin

### Entry Point Registration

The plugin registers via Python entry points in `pyproject.toml`:

```toml
[project.entry-points."quidclaw.plugins"]
crypto = "quidclaw_crypto.plugin:CryptoPlugin"
```

When QuidClaw starts, it discovers `CryptoPlugin` through the `quidclaw.plugins` entry point group.

### Plugin Lifecycle

```
pip install quidclaw-crypto
  -> entry point registered: quidclaw.plugins -> quidclaw_crypto.plugin:CryptoPlugin

QuidClaw startup:
  -> discovers CryptoPlugin via entry points
  -> CryptoPlugin.__init__() imports providers -> @register_provider fires for each
  -> register_commands(cli) adds the `crypto` Click group
  -> get_skills_dir() returns the path to skills/

quidclaw upgrade:
  -> copies skills/quidclaw-crypto/ to .claude/skills/quidclaw-crypto/

quidclaw sync <source-name>:
  -> looks up provider from config -> instantiates the DataSource subclass
  -> calls provider.sync() -> returns SyncResult
```

### Provider Registration

Each provider class uses the `@register_provider` decorator which adds it to the global `PROVIDERS` dict keyed by `provider_name()`. The providers are imported in `CryptoPlugin.__init__()` to trigger registration at plugin load time.

## Development

```bash
python3.13 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest
```

## Testing

32 tests across 4 test files:

- `tests/test_plugin.py` -- plugin registration, commands, skills directory
- `tests/test_commands.py` -- CLI commands (add-exchange, add-wallet, portfolio)
- `tests/test_ccxt_exchange.py` -- CCXT exchange provider sync, incremental sync, status
- `tests/test_evm_explorer.py` -- EVM explorer provider sync, incremental sync, chain validation, status

All API calls are mocked -- no real exchange or blockchain API calls in tests. Test fixtures are in `tests/fixtures/__init__.py`.

```bash
pytest                          # all tests
pytest tests/test_commands.py   # CLI tests only
pytest tests/test_ccxt_exchange.py tests/test_evm_explorer.py  # provider tests only
```

## License

GPL-2.0-only
