Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.xandrlabs.ai/llms.txt

Use this file to discover all available pages before exploring further.

The ALX Protocol settlement layer is a set of deterministic, pure functions that any implementation must execute identically for identical inputs. These functions translate on-chain query payments into curator payouts by applying reputation multipliers and freshness decay, then record each payout in a tamper-evident ledger. All functions are exported from @alx/protocol/economics.

Settlement formula

When settleQuery is called on-chain, the reference AlexandrianRegistryV2 contract splits msg.value across three buckets:
protocolFee     = msg.value * protocolFeesBps / 10000   // 2% = 200 bps
distributable   = msg.value - protocolFee
parentRoyalty_i = distributable * royaltyShareBps_i / 10000
curatorAmount   = distributable - sum(parentRoyalties)
Conservation must hold exactly: protocolFee + sum(parentRoyalties) + curatorAmount = msg.value. Earnings accumulate in pendingWithdrawals[address] and are claimed through pull-based withdrawal.
The sum of royaltyShareBps across all attribution links for a given Knowledge Block MUST be less than or equal to 10000. Contracts that exceed this limit MUST reject the settlement operation.

Constants

ConstantValueDescription
RS_MIN0.01Reputation score floor — ensures brand-new KBs with no query history still earn a minimal payout
RS_MAX3Reputation score ceiling — the highest-reputation KB earns 3× the base payout
HALF_LIFE_DAYS30Freshness decay half-life in days (per PROTOCOL-SPEC §8.3)

Functions

computePayout

Computes the final payout for a Knowledge Block given its base query fee, reputation score, and freshness multiplier. This is the primary economics function you call after normalizing an on-chain score and computing freshness.
function computePayout(base: number, rs: number, freshness: number): number
Formula: payout = base × clamp(rs) × freshness The result is rounded to 6 decimal places and floored at 0.
base
number
required
Base query fee in the unit of account (e.g. ETH or token smallest unit). Sourced from msg.value after protocol fee deduction.
rs
number
required
Raw reputation score. Automatically clamped to [RS_MIN, RS_MAX] = [0.01, 3] before multiplication. Pass the output of normalizeOnChainScore directly.
freshness
number
required
Freshness multiplier in the range (0, 1]. Pass the output of freshnessMultiplier(isoDate) directly. A value of 1.0 means the KB was just published.
return
number
Payout rounded to 6 decimal places, minimum 0.

clampRS

Clamps a raw reputation score to the valid protocol range [RS_MIN, RS_MAX]. You rarely need to call this directly — computePayout clamps internally — but it is useful when you want to display or log a bounded score before computing a payout.
function clampRS(rs: number): number
rs
number
required
Raw reputation score. Values below 0.01 are raised to 0.01; values above 3 are lowered to 3.
return
number
Clamped reputation score in [0.01, 3].

ledgerLeafHash

Produces a deterministic SHA-256 leaf hash for a ledger entry. Use this to verify settlement integrity after distributing payouts — recompute the hash and compare it to the stored value.
function ledgerLeafHash(contentHash: string, amount: number): string
The input to SHA-256 is the UTF-8 string "${contentHash}:${amount}". The output is a 0x-prefixed 64-character lowercase hex string (32 bytes).
SHA-256 is required by the protocol, not a weaker hash. These hashes form a cryptographic integrity check on payout records.
contentHash
string
required
The kbHash (or equivalent contentHash) of the Knowledge Block being settled. Must be the canonical protocol-visible identifier.
amount
number
required
Payout amount for this KB. Use the value returned by computePayout before any further rounding.
return
string
"0x" followed by 64 lowercase hex characters — a 32-byte SHA-256 digest.

Complete example

The following example fetches on-chain data for three Knowledge Blocks, computes their payouts, and verifies the ledger hash for each.
import {
  computePayout,
  ledgerLeafHash,
  normalizeOnChainScore,
  freshnessMultiplier,
} from "@alx/protocol/economics";

interface KBRecord {
  kbHash: string;
  onChainScore: number;   // 0–1000, from ReputationLogic.sol
  publishedAt: string;    // ISO-8601
  baseFee: number;        // distributable share after protocol fee
}

const kbs: KBRecord[] = [
  {
    kbHash: "0xabc123…",
    onChainScore: 750,
    publishedAt: "2026-03-01T00:00:00.000Z",
    baseFee: 0.0049,  // distributable after 2% protocol fee on 0.005 ETH query
  },
  {
    kbHash: "0xdef456…",
    onChainScore: 200,
    publishedAt: "2025-10-15T00:00:00.000Z",
    baseFee: 0.0049,
  },
  {
    kbHash: "0xghi789…",
    onChainScore: 1000,
    publishedAt: "2026-04-10T00:00:00.000Z",
    baseFee: 0.0049,
  },
];

for (const kb of kbs) {
  const rs        = normalizeOnChainScore(kb.onChainScore);
  const freshness = freshnessMultiplier(kb.publishedAt);
  const payout    = computePayout(kb.baseFee, rs, freshness);
  const leaf      = ledgerLeafHash(kb.kbHash, payout);

  console.log({
    kbHash:    kb.kbHash,
    rs:        rs.toFixed(4),
    freshness: freshness.toFixed(4),
    payout:    payout.toFixed(6),
    leaf,
  });
}
Example output:
{ kbHash: '0xabc123…', rs: '2.2270', freshness: '0.7071', payout: '0.007724', leaf: '0x3f9a…' }
{ kbHash: '0xdef456…', rs: '0.5970', freshness: '0.1768', payout: '0.000517', leaf: '0x8c12…' }
{ kbHash: '0xghi789…', rs: '3.0000', freshness: '0.9772', payout: '0.014369', leaf: '0x1a4b…' }
Verify settlement integrity by recomputing ledgerLeafHash(kbHash, payout) after distributing payouts and comparing the result to the stored leaf. Any discrepancy indicates tampered or mismatched payout data.