API Reference

All public functions are documented below. Docstrings are pulled automatically from the package source.

Query Functions

anchorregistry.get_by_arid(ar_id: str, rpc_url: str | None = None) dict[str, Any][source]

Fetch a single anchor record by AR-ID.

Uses the indexed arId topic for a targeted single-event query.

Parameters:
  • ar_id – The AR-ID to look up (e.g. "AR-2026-Pvdp0W5").

  • rpc_url – Optional RPC URL override.

Returns:

Two-level anchor record.

Return type:

dict[str, Any]

Raises:

AnchorNotFoundError – If the AR-ID does not exist on-chain.

anchorregistry.get_by_registrant(wallet_address: str, rpc_url: str | None = None) list[dict[str, Any]][source]

Fetch all anchors registered by a specific wallet address.

Uses the indexed registrant topic.

Parameters:
  • wallet_address – Ethereum wallet address (checksummed or lowercase).

  • rpc_url – Optional RPC URL override.

Returns:

List of two-level anchor records.

Return type:

list[dict[str, Any]]

anchorregistry.get_by_tree(tree_id_plain: str, rpc_url: str | None = None) list[dict[str, Any]][source]

Fetch all anchors belonging to a specific tree.

Uses the indexed treeId topic.

Parameters:
  • tree_id_plain – Human-readable treeId string (e.g. "ar-operator-v1").

  • rpc_url – Optional RPC URL override.

Returns:

List of two-level anchor records.

Return type:

list[dict[str, Any]]

anchorregistry.get_by_type(artifact_type: ArtifactType | int, rpc_url: str | None = None) list[dict[str, Any]][source]

Fetch all anchors of a specific artifact type.

Post-filter on decoded artifactType from event data.

Parameters:
  • artifact_type – An ArtifactType enum member or its integer index.

  • rpc_url – Optional RPC URL override.

Returns:

List of two-level anchor records matching the type.

Return type:

list[dict[str, Any]]

anchorregistry.get_all(from_block: int | None = None, to_block: int | None = None, rpc_url: str | None = None) list[dict[str, Any]][source]

Fetch all anchors from the registry.

Defaults to scanning from DEPLOY_BLOCK to latest.

Parameters:
  • from_block – Starting block number. Defaults to DEPLOY_BLOCK.

  • to_block – Ending block number. Defaults to "latest".

  • rpc_url – Optional RPC URL override.

Returns:

List of all two-level anchor records.

Return type:

list[dict[str, Any]]

Verification

anchorregistry.verify(ar_id: str, file_path: str | None = None, rpc_url: str | None = None) dict[str, Any][source]

Fetch anchor record and optionally verify file integrity.

If file_path is provided, computes SHA256 of the file and compares against manifest_hash on-chain.

Parameters:
  • ar_id – The AR-ID to verify.

  • file_path – Optional local file path for SHA256 integrity check.

  • rpc_url – Optional RPC URL override.

Returns:

Record dict plus verified (bool) and hash_match (bool) keys.

Return type:

dict[str, Any]

Raises:

AnchorNotFoundError – If the AR-ID does not exist on-chain.

Authentication

anchorregistry.authenticate_anchor(ownership_token: str, ar_id: str, rpc_url: str | None = None) dict[str, Any][source]

Authenticate a single anchor by verifying its tokenCommitment on-chain.

Computes keccak256(K || arId) (paper spec Section 4.2) and compares the result against the token_commitment stored in the on-chain Anchored event. Governance anchors (VOID, REVIEW, AFFIRMED, RETRACTION) carry bytes32(0) and are returned as authenticated: False immediately.

Parameters:
  • ownership_token – Ownership token K = keccak256(salt), salt = 32 uniform random bytes. Stored as 0x-prefixed 64-char hex string (bytes32). Never transmitted to AnchorRegistry — known only to the token holder.

  • ar_id – The AR-ID to authenticate (e.g. "AR-2026-Pvdp0W5").

  • rpc_url – Optional RPC URL override.

Returns:

Result dict with keys:

  • authenticated — bool: True if keccak256 proof matches on-chain commitment.

  • ar_id — str: the AR-ID that was checked.

  • token_commitment — str: on-chain commitment (0x-prefixed bytes32 hex).

  • is_user_initiated — bool: False for governance anchors (bytes32(0)).

  • verified — bool: same as authenticated.

Return type:

dict[str, Any]

Raises:

AnchorNotFoundError – If the AR-ID does not exist on-chain.

Examples

>>> from anchorregistry import configure, authenticate_anchor
>>> configure(network="sepolia")
>>> result = authenticate_anchor("0x1a2b3c4d...", "AR-2026-Pvdp0W5")
>>> result["authenticated"]
True
anchorregistry.authenticate_tree(ownership_token: str, root_ar_id: str, rpc_url: str | None = None) dict[str, Any][source]

Authenticate a full tree by verifying ownership and all anchor commitments.

If the tree is sealed, returns immediately with sealed status — the tree is authentic and complete, no further verification needed.

Two-layer verification:

Layer 1 — Tree ownership: Computes keccak256(K || rootArId) (paper spec Section 4.2) and compares against record["tree_id"]. Returns authenticated: False immediately on failure.

Layer 2 — Per-anchor initiation: Calls get_by_tree() and runs authenticate_anchor() for each user-initiated anchor. Governance anchors (bytes32(0) commitment) are counted separately and skipped from verification.

Parameters:
  • ownership_token – Ownership token K = keccak256(salt), salt = 32 uniform random bytes. Stored as 0x-prefixed 64-char hex string (bytes32).

  • root_ar_id – AR-ID of the tree root anchor.

  • rpc_url – Optional RPC URL override.

Returns:

Result dict with keys:

  • authenticated — bool: True if Layer 1 passes and anchors_failed == 0.

  • sealed — bool: True if the tree is sealed.

  • continuation — str: new tree root (if sealed with continuation).

  • tree_id — str: human-readable treeId from the root anchor.

  • root_ar_id — str: the root AR-ID that was checked.

  • anchor_count — int: total anchors in the tree.

  • anchors_verified — int: user-initiated anchors whose commitment matched.

  • anchors_failed — int: user-initiated anchors whose commitment did not match.

  • governance_count — int: governance anchors skipped (bytes32(0)).

Return type:

dict[str, Any]

Raises:

AnchorNotFoundError – If root_ar_id does not exist on-chain.

Examples

>>> from anchorregistry import configure, authenticate_tree
>>> configure(network="sepolia")
>>> result = authenticate_tree("0x1a2b3c4d...", "AR-2026-Pvdp0W5")
>>> result["authenticated"]
True
anchorregistry.is_sealed(root_ar_id: str, rpc_url: str | None = None) dict[str, Any][source]

Check if a tree root has been sealed on-chain.

Parameters:
  • root_ar_id – AR-ID of the tree root anchor.

  • rpc_url – Optional RPC URL override.

Returns:

Result dict with keys:

  • sealed — bool: True if the tree root is sealed.

  • continuation — str: new tree root if set, empty string otherwise.

Return type:

dict[str, Any]

anchorregistry.is_user_initiated(record: dict[str, Any]) bool[source]

Return True if the anchor was initiated by the token holder.

An anchor is user-initiated when its token_commitment is non-zero. Governance anchors (VOID, REVIEW, AFFIRMED, RETRACTION) carry bytes32(0) as a sentinel — enforced by the contract.

Parameters:

record – Two-level anchor record dict as returned by any query function.

Returns:

True if user-initiated (non-zero tokenCommitment). False for AR governance actions.

Return type:

bool

Examples

>>> from anchorregistry import get_by_arid
>>> from anchorregistry.utils import is_user_initiated
>>> record = get_by_arid("AR-2026-Pvdp0W5")
>>> is_user_initiated(record)
True

Watermarking

anchorregistry.watermark(ar_id: str, artifact_type: str | None = None, rpc_url: str | None = None) str[source]

Generate the correct SPDX-Anchor or DAPX-Anchor embedded tag.

  • artifact_type == "CODE"SPDX-Anchor: anchorregistry.ai/{ar_id}

  • All other types → DAPX-Anchor: anchorregistry.ai/{ar_id}

  • If artifact_type is None, resolves via get_by_arid() automatically.

Parameters:
  • ar_id – The AR-ID to watermark.

  • artifact_type – Optional type name string (e.g. "CODE"). If None, looked up on-chain.

  • rpc_url – Optional RPC URL override.

Returns:

The watermark line, e.g. "SPDX-Anchor: anchorregistry.ai/AR-2026-Pvdp0W5".

Return type:

str

Analytics

anchorregistry.to_dataframe(records: list[dict[str, Any]]) Any[source]

Flatten anchor records into a pandas DataFrame.

Type-specific fields in data are flattened with {type_name}_{field_name} column names to avoid semantic collision.

Parameters:

records – List of two-level anchor record dicts.

Returns:

Flat DataFrame suitable for analytics.

Return type:

pandas.DataFrame

Raises:

ImportError – If pandas is not installed.

Configuration

anchorregistry.configure(contract_address: str | None = None, rpc_url: str | None = None, network: str = 'base', deploy_block: int | None = None) None[source]

Configure the active network, contract address, RPC, and deploy block.

Parameters:
  • contract_address – AnchorRegistry contract address to read from. Required — either here or via the ANCHOR_REGISTRY_ADDRESS env var. ar-python ships no default address so callers are always explicit about which contract deployment they’re targeting.

  • rpc_url – Optional RPC URL override. Falls back to BASE_RPC_URL env var, then to the network preset.

  • network – Network name for chain_id + default rpc_url lookup. One of "base", "base-sepolia", "sepolia".

  • deploy_block – Starting block for get_all / get_by_registrant / get_by_tree scans. Strongly recommended — omit and scans start at block 0, which most RPCs reject on wide ranges.

Raises:

ConfigurationError – If network is not a recognised preset name.

Exceptions

exception anchorregistry.exceptions.AnchorNotFoundError[source]

Bases: Exception

Raised when an AR-ID does not exist on-chain.

exception anchorregistry.exceptions.ConfigurationError[source]

Bases: Exception

Raised when the package is used before a contract address is available.