# Verifying a Predge attestation

`GET /v1/attest/{conditionId}` returns a resolved-outcome attestation with an **ed25519 signature**.
Anyone can verify it offline, in any language, without trusting Predge's server — that is the whole
point of the primitive.

## Predge's public key

```
ed25519 (hex, raw 32-byte point):
13fa3d18a369e6c71bf941563ba47822b30182273d5106a0e8fb61c5016352d9
```

Publish this on data.predge.io so consumers can pin it. The signing key never leaves Predge's
infrastructure.

## What's in the response

```json
{
  "attestation": {
    "version": "predge-attest-v1",
    "issuer": "predge.io",
    "algorithm": "ed25519",
    "public_key": "<hex, raw 32-byte point>",
    "canonical": "<the exact bytes that were signed>",
    "signature": "<hex, 64 bytes>",
    "payload": { "version": "...", "issuer": "predge.io", "platform": "polymarket",
                 "condition_id": "0x...", "resolved": true, "resolution": "yes|no",
                 "resolved_at": "...|null", "issued_at": "...",
                 "queried_side": "yes|no", "correct": true|false },
    "verify": "<recipe string>"
  }
}
```

Only immutable settled facts are inside `canonical`/`payload`. `canonical` is the payload as JSON
with keys sorted lexicographically and no whitespace — re-canonicalise `payload` and you must
reproduce `canonical` byte-for-byte.

## Verify (Node.js, zero deps)

```js
import crypto from "node:crypto";

function verifyPredgeAttestation(att, pinnedPubHex) {
  if (att.public_key !== pinnedPubHex) return false;            // pin the key
  const spki = Buffer.concat([
    Buffer.from("302a300506032b6570032100", "hex"),             // ed25519 SPKI prefix
    Buffer.from(att.public_key, "hex"),
  ]);
  const pub = crypto.createPublicKey({ key: spki, format: "der", type: "spki" });
  return crypto.verify(null, Buffer.from(att.canonical, "utf8"),
                       pub, Buffer.from(att.signature, "hex"));
}
```

## Verify (Python, PyNaCl)

```python
from nacl.signing import VerifyKey
from nacl.exceptions import BadSignatureError

def verify_predge_attestation(att, pinned_pub_hex):
    if att["public_key"] != pinned_pub_hex:
        return False
    try:
        VerifyKey(bytes.fromhex(att["public_key"])).verify(
            att["canonical"].encode("utf-8"),
            bytes.fromhex(att["signature"]),
        )
        return True
    except BadSignatureError:
        return False
```

A tampered `canonical` (e.g. flipping `resolution`) or a signature from any other key fails
verification — confirmed by Predge's own test suite and an independent cross-implementation check.

## One-time production proof (owner)

The signing path is unit-tested and the live route is up, but a single **paid** call is the final
end-to-end proof (the signature only appears in the paid 200 response). From a funded buyer:

```bash
npx x402-proxy "https://x402-api-production-266e.up.railway.app/v1/attest/<resolved-conditionId>?side=yes" \
  | jq '.attestation'
# then run the Node/Python verifier above against 13fa3d18…016352d9 → expect true
```
