# Sophi

**A simple language for non-custodial value swaps.**

Sophi has no runtime, no blockchain execution, and no custody of funds.
You describe the swap. Sophi verifies the math and produces a portable proof.

## Install

```
pip install sophi
```

## Write a swap (from-to)

```sophi
swap {
  transfer 0.5 BTC from alice to bob
  transfer 50000 USDT from bob to alice
}
```

Save as `trade.sph` and run:

```
sophi compile trade.sph
```

## Before/after still works

```sophi
swap {
  before:
    alice = 0.5 BTC
    bob = 50000 USDT

  after:
    alice = 50000 USDT
    bob = 0.5 BTC
}
```

## Proofs are external (JSON)

The .sph file never contains signatures or addresses. Signatures are provided
in a separate JSON file after compilation:

```json
{
  "swap_id": "a3f8c2d1e4b7...",
  "signatures": {
    "alice": { "address": "bc1qalice...", "signature": "H7f8c2..." },
    "bob":   { "address": "bc1qbob...",   "signature": "K9d3e1..." }
  }
}
```

Sign the **swap_id** using your Bitcoin wallet. Then call `verify_proof`.

```python
compiled = compile_source(open("trade.sph").read())
result = verify_proof(compiled, proof_json)
assert result["status"] == "signatures_valid"
```

## Proof output

```json
{
  "swap_id": "a3f8c2...",
  "status": "valid",
  "conservation": {
    "BTC":  { "before": "0.5",   "after": "0.5"   },
    "USDT": { "before": "50000", "after": "50000" }
  },
  "delta": {
    "alice": { "BTC": "-0.5",  "USDT": "+50000" },
    "bob":   { "BTC": "+0.5",  "USDT": "-50000" }
  },
  "before": { "alice": "0.5 BTC",    "bob": "50000 USDT" },
  "after":  { "alice": "50000 USDT", "bob": "0.5 BTC"    },
  "htlc": {
    "secret_hash": "a3f8c2...",
    "timeout_blocks": 144,
    "legs": [
      { "from": "alice", "to": "bob",   "asset": "BTC",  "amount": "0.5"   },
      { "from": "bob",   "to": "alice", "asset": "USDT", "amount": "50000" }
    ]
  }
}
```

## Why it is safe

- Non-custodial by construction
- No on-chain execution
- Conservation per asset
- Delta per participant

## License

Business Source License 1.1 - converts to Apache 2.0 after 4 years.
