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 address | 0xD1F216E872a9ed4b90E364825869c2F377155B29 |
| Network | Base mainnet |
| Chain ID | 8453 |
| Subgraph | https://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:
| Value | Type |
|---|
0 | Practice |
1 | Feature |
2 | StateMachine |
3 | PromptEngineering |
4 | ComplianceChecklist |
5 | Rubric |
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();