chore: initialize monorepo with project scaffolding, configs, and CI setup
This commit is contained in:
47
packages/py/aitbc-crypto/src/receipt.py
Normal file
47
packages/py/aitbc-crypto/src/receipt.py
Normal file
@@ -0,0 +1,47 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Dict
|
||||
|
||||
import json
|
||||
from hashlib import sha256
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class Receipt(BaseModel):
|
||||
version: str
|
||||
receipt_id: str
|
||||
job_id: str
|
||||
provider: str
|
||||
client: str
|
||||
units: float
|
||||
unit_type: str
|
||||
started_at: int
|
||||
completed_at: int
|
||||
price: float | None = None
|
||||
model: str | None = None
|
||||
prompt_hash: str | None = None
|
||||
duration_ms: int | None = None
|
||||
artifact_hash: str | None = None
|
||||
coordinator_id: str | None = None
|
||||
nonce: str | None = None
|
||||
chain_id: int | None = None
|
||||
metadata: Dict[str, Any] | None = None
|
||||
|
||||
|
||||
def canonical_json(receipt: Dict[str, Any]) -> str:
|
||||
def remove_none(obj: Any) -> Any:
|
||||
if isinstance(obj, dict):
|
||||
return {k: remove_none(v) for k, v in obj.items() if v is not None}
|
||||
if isinstance(obj, list):
|
||||
return [remove_none(x) for x in obj if x is not None]
|
||||
return obj
|
||||
|
||||
cleaned = remove_none(receipt)
|
||||
return json.dumps(cleaned, separators=(",", ":"), sort_keys=True)
|
||||
|
||||
|
||||
def receipt_hash(receipt: Dict[str, Any]) -> bytes:
|
||||
data = canonical_json(receipt).encode("utf-8")
|
||||
return sha256(data).digest()
|
||||
Reference in New Issue
Block a user