Skip to content

docs: developer docs for working with the contracts - #70

Open
SupremaLex wants to merge 28 commits into
mainfrom
docs/developer-docs
Open

SupremaLex wants to merge 28 commits into
mainfrom
docs/developer-docs

Conversation

@SupremaLex

@SupremaLex SupremaLex commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Developer docs for lib.id/docs, focused on using the contracts. Written against libID-contracts v0.17.0 and @libid/contracts@0.17.0, using the contracts' vocabulary: identity, id, handle, holder, published handle; "owner" means the admin only.

What's in it

  • Get started: an introduction and a read-only quickstart that runs against Ethereum mainnet.
  • Guides:
    • look up a wallet;
    • resolve a handle, including resolveHandleAndId with a saved id;
    • gate a contract;
    • send funds to a handle (HandleEscrow);
    • listen to events, reading from each registry's deploy block in ranges;
    • test on a local chain.
  • ENS: name shape, resolving with viem, and how the resolver and gateway work.
    • Live on Ethereum mainnet: handles.link with HandleResolver 0xc09b…74CE, and the gateway at names.handles.link, which serves chain 1 from the indexer's copy.
  • Concepts:
    • platforms and nodes, with the exact Google id formula and normalization rules;
    • identities and handles;
    • freshness: a just-bound GitHub or X proof reads 0 to 65 minutes old;
    • published handles;
    • what a binding proves, and who you trust, including the notary for Google keys and the indexer for ENS answers.
  • Reference: IdentityRegistry, HandleEscrow, packages, and addresses: one table for production, one for testnets, and a separate section for the two local stacks.
  • Networks: Ethereum mainnet, Sepolia and Eden testnets, each with runnable exports.
  • Resources and advanced: glossary, FAQ, how binding works, and the trust model.
    • The security page lists every contract's owner key per network, with a cast command to check it.
  • Diagrams and layout:
    • four Mermaid diagrams (account model, escrow lifecycle, binding flow, ENS resolution), styled from the site palette;
    • a sidebar with groups;
    • stub pages marked draft: true.
  • docs/STYLE.md: a short writing guide.

Verification

  • Contract facts: addresses, owners, platforms, quoteBind, the ENS owner, resolver and URL, and the gateway's chains were all read from chain-configurations main and from live state on Ethereum, Sepolia and Eden.
  • Live runs:
    • the changed public-network code ran against mainnet: the quickstart, resolve-handle (null-safe), events, the handleNode example and the normalization claims;
    • viem getEnsAddress through the live gateway returned a signed null with no error.
  • Snippets: docs/snippets runs six pages' code unchanged against a local chain, with @libid/contracts@0.17.0: quickstart, lookup, resolve, gate contract, escrow and events. 6 of 6 pass.
  • Site: pnpm -C site install --frozen-lockfile, build and test pass, and 0 of 1435 internal links and anchors are broken.

Open

  • The local-chain project is unpublished. The guides' sample data comes from examples/local-chain, which I can't push (read access only). The local-chain page says so and gives what works today: read against mainnet, or deploy with libid-deploy on anvil (no bindings there). The snippet check depends on that project, so it isn't in CI.
  • Duplicated addresses. The mainnet registry address appears in the runnable exports of five pages. The tables are not generated from chain-configurations.
  • Security contact. The security page needs a real private contact; GitHub private vulnerability reporting is off.
  • ENS operator. The pages say the libID team runs the gateway. Please confirm.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ar21wPcHzNprswTzLJd3MA

Starlight's docs schema requires a title in frontmatter; without it the
content sync fails for the whole site.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Get started, Concepts, Guides, Examples, Reference, Networks and
Resources cover contract interaction. Bridge, notary and verifiers sit
under Advanced for integrators.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Reads a GitHub binding on Eden with viem: resolveHandle, then primaryOf.
Both calls exist on the Eden deployment and on contracts main.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Quickstart, resolve a handle, look up a wallet, gate a contract, send
funds to a handle and listen to events. Snippets use @libid/contracts
from libID-contracts main and ran against a local chain running main's
IdentityNames and HandleEscrow.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Names, resolving with viem, and how the resolver and gateway work,
from HandleResolver on contracts main and the gateway on indexer main.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
resolvePair only tells something when the app stored the account id
behind a handle earlier. The guide shows how to save it with accountsOf
and when the check is pointless.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
IdentityNames and HandleEscrow reference, canonical addresses, Eden and
Ethereum network pages, and a local-chain guide with a script that
deploys main's contracts and binds known handles. Follows main's rename
of claim to bind and the Google userId digest. Makes resolvePair's
wallet comparison precise, qualifies the ENS chain claim, and adds
index-sync guidance to the events guide.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Concept pages for platforms and nodes, accounts and handles, freshness,
primary names and what a binding proves; how binding works and the trust
model; glossary, FAQ, security and packages. Rewrites the introduction
around the guides that exist. Pages that are still stubs are drafts, so
production builds leave them out.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Guides read RPC_URL, IDENTITY_NAMES, HANDLE_ESCROW and the test keys from
the environment that examples/local-chain writes, and the gate contracts
take IdentityNames in their constructor. The escrow guide uses separate
sender and Carol scripts, with refund and claim as alternatives. Fixes an
age check that reverted on future observedAt, paginates the account id
lookup, processes HandleRetired when indexing, and marks ENS names as not
live yet. docs/snippets runs the guides' code against a fresh local chain.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Mermaid diagrams, rendered in the browser by astro-mermaid: how an
account, its handle and its wallet change through a rename and a
reassignment; the escrow's paths from deposit to claim or refund; the
binding flow with its trusted parties and what becomes public; and ENS
resolution for one chain.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Tables get a header row, borders and plain code cells. Diagrams use the
base Mermaid theme with the site font, and take their colours from the
palette variables, so they follow the theme. Trusted parties and the
public result are outlined in the binding diagram, and the escrow
diagram drops its decision diamond.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://docs-developer-docs.previews.lib.id, https://docs-developer-docs-libid.grounded-systems.workers.dev (commit 06d7c1a)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://60f5176e.previews.lib.id, https://60f5176e-libid.grounded-systems.workers.dev 06d7c1a 2026-10-05T16:43:34.760Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://87349edf.previews.lib.id, https://87349edf-libid.grounded-systems.workers.dev 9937fc0 2026-10-05T15:17:43.856Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://25c20859.previews.lib.id, https://25c20859-libid.grounded-systems.workers.dev 92cd3f7 2026-10-05T12:47:03.137Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://1f88ae16.previews.lib.id, https://1f88ae16-libid.grounded-systems.workers.dev 7aea923 2026-10-05T10:03:11.605Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://06518f64.previews.lib.id, https://06518f64-libid.grounded-systems.workers.dev 2ef5d54 2026-10-01T14:17:52.685Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://ee8eec53.previews.lib.id, https://ee8eec53-libid.grounded-systems.workers.dev 49749fb 2026-10-01T09:06:50.338Z Visit the dashboard ↗

IdentityNames is IdentityRegistry, and the docs now use the contracts'
words: identity, id, handle, holder and published handle, with owner
for a contract's admin only. Renames the reference, identities and
published-handles pages, takes the new canonical addresses with a
HandleEscrow beside the registry, and says Eden runs v0.15.0 with no
identities bound yet. The guides and the snippets check move to
@libid/contracts 0.15.0 and IDENTITY_REGISTRY.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
The verifiers move observedAt back by a fixed allowance (5 minutes on
GitHub and X, two hours before a Google token's expiry), so it is never
ahead of the block and a fresh proof already has an age. Freshness,
resolve-a-handle and gate-a-contract said the opposite.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
The verifiers accept a session up to an hour old and a Google token until
it expires, so a just-bound proof reads 5 to 65 minutes old on GitHub and
X and 1 to 2 hours on Google.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Take main's pnpm, Starlight, Astro and Wrangler versions and keep the
Mermaid dependencies; the lockfile is main's plus those two.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
libid-contracts 0.17.0 gives production and the testnets their own
factories, so Addresses lists both tables and says the addresses are
fixed within an environment. Ethereum mainnet is live with the
production table; Eden and the new Sepolia page carry the testnet
table; the quickstart gives both registries.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Every libID contract on Ethereum mainnet, and handles.link with its
HandleResolver, is owned by 0x7e00d33b…128e; Sepolia and Eden share
0xDAEb247f…b907 (owner() read on chain). Security and trust now say
so, and add HandleEscrow's owner: a UUPS upgrade can swap the registry
or move held funds, so the reference no longer says the registry
cannot change.

ENS status follows the chain and the gateway: handles.link resolves
through HandleResolver 0xc09bF842…74CE and names.handles.link, which
serves Ethereum mainnet only; Sepolia's resolver points at the same
gateway and gets no answers. Examples resolve on Ethereum instead of
Base, and "what you trust" adds the ENS name owner and the DNS zone.

refund pays deposits whose refundTo is the caller, not the depositor;
the escrow pages and events say that. The index rules in events use
IdentityBound.published and re-check a published handle's holder, as
publishedHandleOf does.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
The Google id is SHA256("libid.google-user-id" || sub) as 0x and 64
lowercase hex; the platforms page gives the formula and a shell recipe
checked against the GooglePlatformVerifier test vector, and the other
pages link it.

A GitHub or X binding can read 0 minutes old at bind time: createdAt
may run 300 s ahead of the block and observedAt is createdAt - 300.

The airdrop pays with call instead of transfer, after marking the
identity claimed, so Safe and ERC-4337 holders can receive it. The
page's Solidity still compiles with forge build.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
The pages describe libID-contracts v0.17.0, so the snippets check pins
the matching package and packages.md names that version instead of
"0.15.0 or later". resolveHandleAndId was listed twice.

Every name the pages import from @libid/contracts resolves in 0.17.0,
and the check passes on all six pages against a copy of the local-chain
project. That project is not published, so the README says the check
needs a local copy of it and stays out of CI.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
…tead

The guides' output comes from an examples local-chain project that is
not published, so the docs no longer tell readers to clone it. The
local-chain page now offers what works today: the read-only code
against Ethereum mainnet, or the full stack on anvil from
chain-configurations' local-dev.toml with the released libid-deploy
(nothing bound, so no binding or claim). Its test data stays, labelled
as the source of the guides' output.

Addresses separates the two local stacks: local-dev.toml's CREATE3
table (registry 0x105b32e3…) and the local-chain project's plain-CREATE
registry and escrow (0xe7f1725E…, 0x0B306BF9…). The network pages and
the quickstart drop their copied address tables and keep only the
export lines a command needs.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
GoogleJwtRoots.rotate takes a notary-attested reading of Google's key
list from anyone (mainnet GoogleJwtRoots points at NotaryService
0x2feeE7C8…), so a false notary signature can install a key that binds
any Google account. Trust, trust model and how binding works say so
instead of "Google needs no notary".

The ENS gateway answers from the indexer's copy of IdentityRegistry,
which may lag a few blocks, and signs for 5 minutes. The diagram,
step 3, the "compared to IdentityRegistry" section and the trust list
now say that, and the trust list names the indexer. The owner key is
linked from Security instead of repeated.

Bold-led running text in trust, how binding works and the
IdentityRegistry term list becomes plain text or headings.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
The normalization list follows HandleNormalizer at v0.17.0: spaces
trimmed, the @ strip before the length check, the hyphen rule only
where allowHyphen (GitHub), Google's own character set and only its
one-@ shape check, so -a@… and a--b@… are accepted. Checked with the
package's normalize under mainnet's rulesOf.

TypeScript handleNode takes handleHash(raw, rules), not a handle; the
example computes it that way and matches handleNodeOf on mainnet.
pay-a-handle says GitHub and X both lowercase and drop a leading @.

Escrow rounds are per handle and token; a claim closes the round only
for the tokens it paid out.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Events read from FROM_BLOCK, the registry's deploy block (Ethereum
26122774, Sepolia 11839189, Eden 276480017, from the creation
transactions and code-at-block), in 5000-block ranges, instead of
from block 0. The network pages export it with RPC_URL and both
addresses, and local-chain's public-network block sets HANDLE_ESCROW
and FROM_BLOCK too.

resolve-handle's idOf returns null when nobody holds the handle, so it
runs on mainnet where octocat is unbound. Eden no longer claims to have
no bindings. The version statement lives once, on Addresses. The intro
links Networks to Ethereum mainnet, and the quickstart asks for Node.js
22.12, as the package engines do.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
A js block after a cast, forge create or ./bind.sh block starts a new
module with the page's setup block in front, and a page with ./bind.sh
but no js no longer dereferences a missing setup. Modules go to a
temporary directory under docs/snippets, so imports still resolve, and
it and the mkdtemp work directory are removed in finally; mkdirSync
replaces spawning mkdir.

Assisted-by: Claude Opus 5.5
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
@SupremaLex
SupremaLex marked this pull request as ready for review October 6, 2026 08:20

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant