did#
Decentralized Identifiers for OCaml.
Implements the W3C DID Core 1.0 syntax and document data
model, with method-specific resolvers for did:web and
did:plc shipped as sublibraries. A DID is a URI of the
form did:<method>:<method-specific-id> that identifies a subject
without a centralised registry; resolution yields a DID document
describing verification methods and service endpoints.
Packages#
did— pure DID syntax and document data model.did-web—did:webresolver (HTTPS).did-plc—did:plcresolver (plc.directory lookup).
Installation#
Install with opam:
$ opam install did did-web did-plc
If opam cannot find the packages, they may not yet be released in
the public opam-repository. Add the overlay repository, then
install them:
$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install did did-web did-plc
Usage#
Syntax#
Parse a DID and extract its method and method-specific id:
# let did = Did.of_string_exn "did:plc:z72i7hdynmk6r22z27h6tvur" in
(Did.method_name did, Did.method_specific_id did)
- : string * string = ("plc", "z72i7hdynmk6r22z27h6tvur")
Method names must be lowercase; the method-specific id preserves case:
# Did.of_string "did:Web:example.com"
- : (Did.t, Did.error) result =
Error (`Msg "invalid character 'W' in DID method name at offset 4")
URL construction#
did:web resolution is a pure function of the DID. The spec maps
method-specific ids to HTTPS paths using : as a segment separator:
# Did_web.url_of_did (Did.of_string_exn "did:web:example.com")
- : (string, Did.error) result =
Ok "https://example.com/.well-known/did.json"
# Did_web.url_of_did (Did.of_string_exn "did:web:example.com:users:alice")
- : (string, Did.error) result =
Ok "https://example.com/users/alice/did.json"
Resolution#
did:web and did:plc resolvers require an Eio runtime:
let resolve_web env did =
Eio.Switch.run @@ fun sw ->
match
Did_web.resolve
~sw ~clock:(Eio.Stdenv.clock env) ~net:(Eio.Stdenv.net env) did
with
| Ok doc -> Fmt.pr "resolved: %a@." Did.Document.pp doc
| Error e -> Fmt.pr "failed: %a@." Did_web.pp_error e
Service lookup#
A DID document indexes service endpoints by id (fragment) and by
type. ATProto uses #atproto_pds:
# let did = Did.of_string_exn "did:web:example.com" in
let doc =
Did.Document.v
~service:[{
id = "#atproto_pds";
type_ = ["AtprotoPersonalDataServer"];
service_endpoint = "https://pds.example.com";
}]
did in
Option.map
(fun (s : Did.Document.service) -> s.service_endpoint)
(Did.Document.service_by_id doc "#atproto_pds")
- : string option = Some "https://pds.example.com"
Licence#
ISC