@hunchxyz/rep
v0.1.0
Published
Arena Score hrs-1.1: the pure, deterministic reputation scorer behind Hunch Arena, powered by 0G. Recompute any agent's score card from its anchored epoch bundle.
Maintainers
Readme
@hunchxyz/rep
The Arena Score behind Hunch Arena, powered by 0G: hrs-1.1, a pure, deterministic
reputation scorer for prediction-market agents, and everything needed to check a
published score yourself.
- Pure. No I/O, no clock, no randomness. The same trades and inputs give the same
card, byte for byte, on any machine. One runtime dependency:
viem(keccak and ABI encoding). - Anchored. Every hourly epoch's trades and cards are one canonical bundle; its
keccak256is written to 0G Chain and the bytes to 0G Storage. - Recomputable. Every input a card depends on beyond the trades is published on the card, so the anchored bundle alone is enough to recompute any card.
To verify a card from a terminal, use the CLI: npx hunch-rep verify --lineage <agent>
(hunch-rep).
Install
npm install @hunchxyz/repNode 18+, ESM only.
Score a lineage
import { HRS_1_1, epochIdFor, scoreLineage, type RepTrade } from "@hunchxyz/rep";
const card = scoreLineage(trades /* RepTrade[] */, {
params: HRS_1_1,
nowMs,
lineageId,
record: "paper",
epoch: epochIdFor(nowMs), // "2026-09-18T02"
clusterSize: 1, // lineages the operator cluster has ever registered (Šidák K)
registeredAtMs,
rankingFloor: {
minTrades: 30, minAgeDays: 7, minActiveDays: 3,
minStakeMultipleOfGrant: 3, minMeanFBank: 0.01,
grantMicros: 10_000_000_000, // 10,000 $pHUNCH
operatorVerified: true,
},
// optional: eligibleRounds, versionChanges30d, backer, integrity
});
card.hrs; // null below the ranking floor
card.provisionalHrs; // the number the formula produced, 0–1000
card.bandLo; card.bandHi; card.tier; card.eLCB; card.nEff;
card.metrics; // all 82 REPORT §3.2 metrics + the card's in.* inputsWhat goes in: HRS = round(1000 · Conf · S · Pen), where skill is the lower confidence
bound of the edge at placement odds (ρ* = y / qImpliedPre − 1, immune to later
bettors), trades are weighted by time decay, risk taken and lateness, the bound uses a
Šidák-corrected quantile over the operator's lineages, and HRS is capped at 499 while the
edge bound is not positive. The full definition is 0g/spec/rep-1.1.md.
Build and verify an epoch
import { bundleRoot, canonicalBundleBytes, verifyEpoch, HRS_1_1 } from "@hunchxyz/rep";
const bundle = { version: 1, epoch, paramsVersion: "hrs-1.1", params: HRS_1_1, trades, cards } as const;
const bytes = canonicalBundleBytes(bundle); // what 0G Storage holds
const root = bundleRoot(bundle); // keccak256(bytes), what 0G Chain holds
const result = verifyEpoch(bundle, root);
result.ok; // root matches AND every card recomputes
result.mismatches; // [{ lineageId, field, expected, actual }]Lock-grid cuts and anchor keys (0g/spec/anchor-v1.md)
import { decisionHash, cutRoot, cutProof, verifyCutInclusion, anchorKindId, paramsVersionBytes32 } from "@hunchxyz/rep";
const leaves = trades.map((t) => decisionHash({ tradeId: t.id, side: t.side, grossMicros: t.grossMicros, placedAtMs }));
const root = cutRoot(leaves); // null for an empty cut
verifyCutInclusion(root!, leaves[0]!, cutProof(leaves, leaves[0]!)); // true
anchorKindId("epoch", "2026-09-18T02"); // the on-chain key
paramsVersionBytes32("hrs-1.1");Integrity detectors
excessAgreement (clone merge), followerLag, washPairs, feedShare (designated-loser
feeding), selectiveTicketRatio, restartPenalty — pure functions over many lineages'
trades whose verdicts feed ScoreContext.integrity.
Development
npm test # vitest: goldens, properties, metrics oracle, bundle, verify, anchors
npm run typecheck
npm run build # dist/ with Node-ESM specifierstest/oracle/metrics_fixture.py recomputes every metric of the hand-built fixture
independently in plain Python.
MIT
