diff --git a/packages/identity/README.md b/packages/identity/README.md index 8b7af66fdcc..e932728323f 100644 --- a/packages/identity/README.md +++ b/packages/identity/README.md @@ -1,4 +1,3 @@ - # `@atproto/identity` Typescript library for decentralized identities in [atproto](https://atproto.com) using DIDs and handles @@ -6,7 +5,190 @@ Typescript library for decentralized identities in [atproto](https://atproto.com [![NPM](https://img.shields.io/npm/v/@atproto/identity)](https://www.npmjs.com/package/@atproto/identity) [![Github CI Status](https://github.com/bluesky-social/atproto/actions/workflows/repo.yaml/badge.svg)](https://github.com/bluesky-social/atproto/actions/workflows/repo.yaml) +## Example + +Resolving a Handle and verifying against DID document: + +```typescript +const didres = new DidResolver({}) +const hdlres = new HandleResolver({}) + +const handle = 'atproto.com' +const did = await hdlres.resolve(handle) + +if (did == undefined) { + throw new Error('expected handle to resolve') +} +console.log(did) // did:plc:ewvi7nxzyoun6zhxrhs64oiz + +const doc = await didres.resolve(did) +console.log(doc) + +// additional resolutions of same DID will be cached for some time, unless forceRefresh flag is used +const doc2 = await didres.resolve(did, true) + +// helper methods use the same cache +const data = await didres.resolveAtprotoData(did) + +if (data.handle != handle) { + throw new Error('invalid handle (did not match DID document)') +} +``` + + +## :toolbox: Functions + +- [getDid](#gear-getdid) +- [getKey](#gear-getkey) +- [getHandle](#gear-gethandle) +- [getPds](#gear-getpds) +- [getFeedGen](#gear-getfeedgen) +- [getNotif](#gear-getnotif) +- [parseToAtprotoDocument](#gear-parsetoatprotodocument) +- [ensureAtpDocument](#gear-ensureatpdocument) + +### :gear: getDid + +| Function | Type | +| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `getDid` | `(doc: { id?: string; alsoKnownAs?: string[]; verificationMethod?: { id?: string; type?: string; controller?: string; publicKeyMultibase?: string; }[]; service?: { id?: string; type?: string; serviceEndpoint?: string or Record<...>; }[]; }) => string` | + +### :gear: getKey + +| Function | Type | +| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `getKey` | `(doc: { id?: string; alsoKnownAs?: string[]; verificationMethod?: { id?: string; type?: string; controller?: string; publicKeyMultibase?: string; }[]; service?: { id?: string; type?: string; serviceEndpoint?: string or Record<...>; }[]; }) => string` | + +### :gear: getHandle + +| Function | Type | +| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `getHandle` | `(doc: { id?: string; alsoKnownAs?: string[]; verificationMethod?: { id?: string; type?: string; controller?: string; publicKeyMultibase?: string; }[]; service?: { id?: string; type?: string; serviceEndpoint?: string or Record<...>; }[]; }) => string` | + +### :gear: getPds + +| Function | Type | +| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `getPds` | `(doc: { id?: string; alsoKnownAs?: string[]; verificationMethod?: { id?: string; type?: string; controller?: string; publicKeyMultibase?: string; }[]; service?: { id?: string; type?: string; serviceEndpoint?: string or Record<...>; }[]; }) => string` | + +### :gear: getFeedGen + +| Function | Type | +| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `getFeedGen` | `(doc: { id?: string; alsoKnownAs?: string[]; verificationMethod?: { id?: string; type?: string; controller?: string; publicKeyMultibase?: string; }[]; service?: { id?: string; type?: string; serviceEndpoint?: string or Record<...>; }[]; }) => string` | + +### :gear: getNotif + +| Function | Type | +| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `getNotif` | `(doc: { id?: string; alsoKnownAs?: string[]; verificationMethod?: { id?: string; type?: string; controller?: string; publicKeyMultibase?: string; }[]; service?: { id?: string; type?: string; serviceEndpoint?: string or Record<...>; }[]; }) => string` | + +### :gear: parseToAtprotoDocument + +| Function | Type | +| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `parseToAtprotoDocument` | `(doc: { id?: string; alsoKnownAs?: string[]; verificationMethod?: { id?: string; type?: string; controller?: string; publicKeyMultibase?: string; }[]; service?: { id?: string; type?: string; serviceEndpoint?: string or Record<...>; }[]; }) => Partial<...>` | + +### :gear: ensureAtpDocument + +| Function | Type | +| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ensureAtpDocument` | `(doc: { id?: string; alsoKnownAs?: string[]; verificationMethod?: { id?: string; type?: string; controller?: string; publicKeyMultibase?: string; }[]; service?: { id?: string; type?: string; serviceEndpoint?: string or Record<...>; }[]; }) => AtprotoData` | + +## :wrench: Constants + +- [verificationMethod](#gear-verificationmethod) +- [service](#gear-service) +- [didDocument](#gear-diddocument) + +### :gear: verificationMethod + +| Constant | Type | +| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `verificationMethod` | `ZodObject<{ id: ZodString; type: ZodString; controller: ZodString; publicKeyMultibase: ZodOptional; }, "strip", ZodTypeAny, { ...; }, { ...; }>` | + +### :gear: service + +| Constant | Type | +| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `service` | `ZodObject<{ id: ZodString; type: ZodString; serviceEndpoint: ZodUnion<[ZodString, ZodRecord]>; }, "strip", ZodTypeAny, { ...; }, { ...; }>` | + +### :gear: didDocument + +| Constant | Type | +| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `didDocument` | `ZodObject<{ id: ZodString; alsoKnownAs: ZodOptional>; verificationMethod: ZodOptional; }, "strip", ZodTypeAny, { ...; }, { ...; }>, "many">>; service: ZodOptional<...>; }, "str...` | + +## :factory: DidNotFoundError + +## :factory: PoorlyFormattedDidError + +## :factory: UnsupportedDidMethodError + +## :factory: PoorlyFormattedDidDocumentError + +## :factory: UnsupportedDidWebPathError + +## :factory: HandleResolver + +Resolves a handle (domain name) to a DID. + +Calling code must validate handle/DID pariing against the DID document itself. + +### Methods + +- [parseDnsResult](#gear-parsednsresult) + +#### :gear: parseDnsResult + +| Method | Type | +| ---------------- | ---------------------------------------- | +| `parseDnsResult` | `(chunkedResults: string[][]) => string` | + +## :factory: BaseResolver + +### Methods + +- [validateDidDoc](#gear-validatediddoc) + +#### :gear: validateDidDoc + +Throws if argument is not a valid DidDocument. + +Only checks type structure, does not parse internal fields. + +| Method | Type | +| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `validateDidDoc` | `(did: string, val: unknown) => { id?: string; alsoKnownAs?: string[]; verificationMethod?: { id?: string; type?: string; controller?: string; publicKeyMultibase?: string; }[]; service?: { id?: string; type?: string; serviceEndpoint?: string or Record<...>; }[]; }` | + +Parameters: + +- `did`: - DID to verify against field in the document itself +- `val`: - object to verify structure as a DidDocument + +## :factory: DidWebResolver + +Resolves did:web DIDs. + +Supports only top-level (domain) DIDs, not paths (with additional ":" segments in the DID). UnsupportedDidWebPathError will be thrown if path segments are detected. + +## :factory: DidPlcResolver + +## :factory: DidResolver + +## :factory: IdResolver + +Wrapper of a DID resolver and handle resolver. + +Calling code is responsible for cross-validate handle/DID pairing. + +## :factory: MemoryCache + +Tiered in-memory cache. + +Entries older than maxTTL are considered invalid and not returned. Entries older than staleTTL are returned, marked as stale. + ## License