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.

ALX Protocol uses CIDv1 to give every KB envelope a stable IPFS address. The CID is derived from the SHA-256 hash of the canonical JSON bytes of the normalized envelope, encoded as a CIDv1 with the raw codec (0x55) and SHA-256 multihash (0x12). The result is a bafy... base32 multibase string suitable for pinning on IPFS and passing as rootCid to publishKB. The CID is not the same as kbHash. They differ in both hash function (SHA-256 vs Keccak-256) and representation (multibase CIDv1 vs 0x-prefixed hex). Use kbHash as the on-chain identifier and cidV1 as the IPFS address.
import { cidV1FromCanonicalSync, cidV1FromCanonical } from "@alx/protocol";

Signatures

cidV1FromCanonicalSync (preferred in server environments)

function cidV1FromCanonicalSync(canonicalJson: string): string
Synchronous. Computes SHA-256 using Node’s built-in crypto module, wraps the digest in a multihash, and constructs the CIDv1. Because it uses crypto from Node’s standard library, it does not require a Web Crypto polyfill and has no async overhead.

cidV1FromCanonical (browser / non-Node environments)

function cidV1FromCanonical(canonicalJson: string): Promise<string>
Async variant. Uses the multiformats SHA-256 implementation, which works in browser environments and any runtime that does not expose Node’s crypto module. Both functions produce identical output for the same input.

Parameters

canonicalJson
string
required
The canonical JSON string produced by canonicalize() over the normalized, hash-scoped envelope. You must canonicalize the envelope yourself before calling these functions — they do not call canonicalize() internally.

Return value

cidV1
string
A CIDv1 multibase string (base32 encoding, bafy... prefix). This is the IPFS content address for the canonical envelope.

Example: compute CID and publish a KB

import { canonicalize, kbHashFromEnvelope, cidV1FromCanonicalSync } from "@alx/protocol";
import { ethers } from "ethers";
import { REGISTRY_ABI } from "@alx/protocol";

const CONTRACT_ADDRESS = "0xD1F216E872a9ed4b90E364825869c2F377155B29";

const envelope = {
  type: "practice",
  domain: "software.security",
  sources: [],
  artifactHash: "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890ab",
  tier: "open",
  payload: {
    type: "practice",
    rationale: "Validate all inputs at trust boundaries.",
    contexts: [],
    failureModes: [],
  },
};

// 1. Compute KB identity hash
const kbHash = kbHashFromEnvelope(envelope);

// 2. Derive the IPFS CID from the same canonical bytes
//    kbHashFromEnvelope normalizes and canonicalizes internally;
//    replicate that here by canonicalizing the normalized envelope
import { canonicalize } from "@alx/protocol";
// (normalizeForHash is applied inside kbHashFromEnvelope — for the CID
//  you can use cidV1FromEnvelope which handles normalization automatically)
import { cidV1FromEnvelope } from "@alx/protocol";
const rootCid = await cidV1FromEnvelope(envelope);

// 3. Publish on-chain
const registry = new ethers.Contract(CONTRACT_ADDRESS, REGISTRY_ABI, signer);

await registry.publishKB(
  kbHash,    // bytes32
  rootCid,   // IPFS CIDv1 string
  0,         // kbType: 0 = Practice
  [],        // parentIds: bytes32[]
  0,         // royaltyBps
  { value: ethers.parseEther("0.001") }
);

Choosing between the two functions

SituationRecommended function
Node.js server, protocol tooling, conformance testscidV1FromCanonicalSync — no async overhead, uses native crypto
Browser, Deno, edge runtime without Node cryptocidV1FromCanonical — uses multiformats SHA-256
Starting from a full envelope objectcidV1FromEnvelope(envelope) — normalizes + canonicalizes before hashing

Notes

  • cidV1 and kbHash use the same canonical JSON input but different hash functions and output formats. Never use a cidV1 value as a bytes32 on-chain identifier, and never use a kbHash hex string as an IPFS address.
  • The raw codec 0x55 means the CID addresses the canonical JSON bytes directly, with no IPLD framing. The SHA-256 multihash code is 0x12.
  • Both functions produce identical results for the same canonicalJson string. The async function is not slower by design — the difference is only the underlying crypto primitive.