Skip to content
Crifine

@crifine/sdk

The measurement method, an independent verifier, and the decision policy — all pure, all checkable.

npm install @crifine/sdk

Zero runtime dependencies. Node 20+, Workers, Deno, browser.

Verify a published number

This is the part that makes keyless verification real rather than rhetorical. It recomputes an estimate from its own evidence and reports whether the claim follows from the data beside it.

import { verifyUrl } from "@crifine/sdk";

const verdict = await verifyUrl("https://crifine.app/api/v1/exit/aave-v3-weth");

if (!verdict.matches) {
  console.error("does not follow from its evidence:", verdict.problems);
}
verdict.deltaBps; // signed: negative means the claim was optimistic

Run the method

import { walkLadder } from "@crifine/sdk/ladder";

const result = walkLadder(
  [
    { bps: 5,  usd: 612_000 },
    { bps: 10, usd: 548_000 },
    { bps: 25, usd: 471_000 },
  ],
  4820,       // oracle price
  1_000_000,  // the size you actually want to move
);

result.exitGapPct;
result.exceedsBook; // true = past the edge of the data, not a price
  • Size is required. walkLadder throws on zero — there is no such thing as *the* fill price.
  • Past the book is flagged, not extrapolated. The remainder is charged at a penalty rate and exceedsBook is set.

Decide what to do

Every agent that consumes this data writes the same branch. decide writes it once, so the ordering is settled in one place — and the ordering is the part people get wrong.

import { decide, blocks } from "@crifine/sdk/policy";

const decision = decide(estimate, {
  maxGapPct: -2,        // required, and must be negative
  minDaysObserved: 30,  // refuse an estimate with too little record behind it
  allowClosedMarket: false,
  minResizeUsd: 50_000,
});

decision.action;  // "proceed" | "resize" | "hold" | "defer" | "refuse"
decision.reason;  // one sentence, safe to log
blocks(decision); // true for refuse / hold / defer

Derivations

FunctionAnswers
stressWindow(series, days)Worst condition in a window, not the average.
depthDecay(series)How fast the book thinned after the largest move.
rankRoutes(estimates)Best venue at one size. Throws on mixed sizes.
gapSeries(series, ladder, size)The record recomputed at *your* size.
severity(gapPct)ok / watch / bad banding.

Call the API

import { CrifineClient } from "@crifine/sdk";
import { x402Fetch } from "@crifine/x402";

const crifine = new CrifineClient({
  fetch: x402Fetch({ maxPerCall: 0.01, settle }),
});

await crifine.exit("aave-v3-weth", 5_000_000);
await crifine.evidence("aave-v3-weth"); // free, keyless, no payment

Payment is injected, not bundled, so the package stays dependency-free for callers who only read the free endpoints. Transient failures (429, 5xx) are retried with backoff; a 402 is never retried — payment belongs to the injected fetch, and retrying it blind is how an unattended agent pays twice.