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 Alexandrian Registry is the on-chain source of truth for ALX Protocol Knowledge Blocks. It records each KB’s kbHash (contentHash), IPFS root CID, type, lineage, and artifactHash. It also handles query settlement and accumulates earnings in a pull-based withdrawal model. The reference indexer (subgraph) mirrors registry events for efficient off-chain discovery. On-chain state is authoritative; the subgraph is for querying only.
Always verify the contract address and chain ID before sending a transaction. The registry is deployed on Base mainnet (chain ID 8453) only. Sending a transaction to the wrong chain or contract will result in an unrecoverable loss of funds.

Network details

Contract address0xD1F216E872a9ed4b90E364825869c2F377155B29
NetworkBase mainnet
Chain ID8453
Subgraphhttps://api.studio.thegraph.com/query/1742359/alexandrian-protocol/version/latest

Connecting to the registry

import { ethers } from "ethers";
import { REGISTRY_ABI } from "@alx/protocol";

const CONTRACT_ADDRESS = "0xD1F216E872a9ed4b90E364825869c2F377155B29";

// Read-only (no signer required)
const provider = new ethers.JsonRpcProvider("https://mainnet.base.org");
const registry = new ethers.Contract(CONTRACT_ADDRESS, REGISTRY_ABI, provider);

// Write operations require a signer
const signer = await provider.getSigner();
const registryWithSigner = new ethers.Contract(CONTRACT_ADDRESS, REGISTRY_ABI, signer);

KB types

The kbType argument in publishKB is a uint8 enum:
ValueType
0Practice
1Feature
2StateMachine
3PromptEngineering
4ComplianceChecklist
5Rubric

publishKB

Registers a new Knowledge Block on-chain. The caller must send at least 0.001 ETH as a stake. The registry rejects duplicate kbHash values with AlreadyPublished.
publishKB(
  kbHash:     bytes32,   // 0x-prefixed 32-byte hex — KB identity hash
  rootCid:    string,    // IPFS CIDv1 string (bafy...)
  kbType:     uint8,     // see KB type table above
  parentIds:  bytes32[], // parent kbHash values (max 8)
  royaltyBps: uint16,    // royalty in basis points (0–10000; e.g. 500 = 5%)
  overrides:  { value: bigint }
): Promise<ContractTransactionResponse>
Constraints:
  • parentIds.length must be <= 8
  • royaltyBps must be in the range 0–10000 (basis points)
  • value must be at least 0.001 ETH
import { ethers } from "ethers";
import { REGISTRY_ABI, kbHashFromEnvelope, cidV1FromEnvelope } from "@alx/protocol";

const CONTRACT_ADDRESS = "0xD1F216E872a9ed4b90E364825869c2F377155B29";
const registry = new ethers.Contract(CONTRACT_ADDRESS, REGISTRY_ABI, signer);

const kbHash = kbHashFromEnvelope(envelope);
const rootCid = await cidV1FromEnvelope(envelope);

const tx = await registry.publishKB(
  kbHash,
  rootCid,
  0,           // Practice
  [],          // no parents
  500,         // 5% royalty
  { value: ethers.parseEther("0.001") }
);

const receipt = await tx.wait();
console.log("Published in block", receipt.blockNumber);

settleQuery

Distributes a query fee across the KB attribution DAG. The protocol retains 2% (200 bps); the remaining value flows through royaltyBps weights to contributing KB curators. Earnings accumulate in pendingWithdrawals[address] and are withdrawn separately.
settleQuery(
  queryId:  bytes32,   // unique query identifier
  kbIds:    bytes32[], // KBs attributed to this query response
  queryFee: uint256,   // fee amount in wei
  overrides: { value: bigint } // must equal queryFee
): Promise<ContractTransactionResponse>
const queryFee = ethers.parseEther("0.01");

const tx = await registry.settleQuery(
  queryId,
  [kbId1, kbId2],
  queryFee,
  { value: queryFee }
);

await tx.wait();

getArtifactHash

Returns the artifactHash stored at publication time for a given kbId. Use this to verify that artifact bytes retrieved from IPFS match the on-chain commitment.
getArtifactHash(kbId: bytes32): Promise<string>
import { artifactHashFromBytes } from "@alx/protocol";

const onChainHash = await registry.getArtifactHash(kbId);

const retrievedBytes = new TextEncoder().encode(
  JSON.stringify(retrievedArtifact, null, 2) + "\n"
);
const localHash = artifactHashFromBytes(retrievedBytes);

if (onChainHash !== localHash) {
  throw new Error("Artifact integrity check failed");
}

Pull-based withdrawals

Earnings from query settlement accumulate in pendingWithdrawals[yourAddress] and are not automatically sent to your wallet. You must call the withdraw() function on the registry contract to claim them. This pull-based model protects against reentrancy and batching attacks.
// Check pending balance
const pending = await registry.pendingWithdrawals(walletAddress);
console.log("Claimable:", ethers.formatEther(pending), "ETH");

// Withdraw
const tx = await registryWithSigner.withdraw();
await tx.wait();