CORE CONCEPTS

SDKs & Verification

TypeScript SDK

1import { keccak_256 } from "@noble/hashes/sha3";
2
3// Minimal RFC-8785 JCS canonicalization
4export function jcs(obj: any): string {
5  if (obj === null) return "null";
6  if (typeof obj === "number") return JSON.stringify(obj);
7  if (typeof obj === "string" || typeof obj === "boolean") 
8    return JSON.stringify(obj);
9  if (Array.isArray(obj)) 
10    return "[" + obj.map(jcs).join(",") + "]";
11  
12  const keys = Object.keys(obj).sort();
13  return "{" + keys.map(k => 
14    JSON.stringify(k) + ":" + jcs(obj[k])
15  ).join(",") + "}";
16}
17
18export function hashPayload(
19  payloadNoNonce: any, 
20  nonceHex: string
21): `0x${string}` {
22  const encoder = new TextEncoder();
23  const a = encoder.encode(jcs(payloadNoNonce));
24  const b = Uint8Array.from(
25    Buffer.from(nonceHex.replace(/^0x/, ''), 'hex')
26  );
27  const cat = new Uint8Array(a.length + b.length);
28  cat.set(a, 0);
29  cat.set(b, a.length);
30  const h = keccak_256(cat);
31  return ("0x" + Buffer.from(h).toString("hex")) as `0x${string}`;
32}

Python SDK

1import json
2from eth_hash.auto import keccak
3
4def jcs(obj):
5    if obj is None: return "null"
6    if isinstance(obj, bool): return "true" if obj else "false"
7    if isinstance(obj, (int, float)): 
8        return json.dumps(obj, separators=(",", ":"))
9    if isinstance(obj, str): 
10        return json.dumps(obj, ensure_ascii=False, separators=(",", ":"))
11    if isinstance(obj, list): 
12        return "[" + ",".join(jcs(x) for x in obj) + "]"
13    
14    keys = sorted(obj.keys())
15    return "{" + ",".join(
16        json.dumps(k, ensure_ascii=False) + ":" + jcs(obj[k]) 
17        for k in keys
18    ) + "}"
19
20def hash_payload(payload_no_nonce: dict, nonce_hex: str) -> str:
21    canonical = jcs(payload_no_nonce).encode("utf-8")
22    nonce = bytes.fromhex(
23        nonce_hex[2:] if nonce_hex.startswith("0x") else nonce_hex
24    )
25    return "0x" + keccak(canonical + nonce).hex()

CLI Verifier

1# install: node >=18
2npx chaingit/chaintick-verifier verify --id <signalId>
3
4# or local file
5npx chaingit/chaintick-verifier verify --payload payload.json --nonce 0x...