-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathmethod.ts
More file actions
150 lines (140 loc) · 5.62 KB
/
method.ts
File metadata and controls
150 lines (140 loc) · 5.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import { fetchLogFromIdentifier, getActiveDIDs, maybeWriteTestLog } from "./utils";
import { DidResolutionError } from './interfaces';
import type { CreateDIDInterface, CreateDIDResult, DIDLog, UpdateDIDInterface, UpdateDIDResult, DeactivateDIDInterface, ResolutionOptions, WitnessProofFileEntry } from './interfaces';
import * as v1 from './method_versions/method.v1.0';
import * as v0_5 from './method_versions/method.v0.5';
const LATEST_VERSION = '1.0';
function getWebvhVersionFromMethod(method?: string): string {
if (!method) return LATEST_VERSION;
const match = method.match(/^did:webvh:(\d+\.\d+)$/);
return match ? match[1] : LATEST_VERSION;
}
function getWebvhVersionFromLog(log: DIDLog): string {
if (log && log.length > 0 && log[0].parameters && log[0].parameters.method) {
return getWebvhVersionFromMethod(log[0].parameters.method);
}
return LATEST_VERSION;
}
function getWebvhVersionFromOptions(options: any): string {
if (options && options.method) {
return getWebvhVersionFromMethod(options.method);
}
return LATEST_VERSION;
}
/**
* Creates a new did:webvh DID and initial DID log.
*
* @param options DID creation options.
* @returns The created DID, resolved document, and DID log.
*/
export const createDID = async (options: CreateDIDInterface): Promise<CreateDIDResult> => {
const version = getWebvhVersionFromOptions(options);
const result = version === '0.5'
? await v0_5.createDID(options)
: await v1.createDID(options);
maybeWriteTestLog(result.did, result.log);
return result;
};
/**
* Resolves a DID by fetching and validating its DID log.
*
* For `did:webvh:1.0`, `fastResolve` is forwarded to the v1 resolver.
* For `did:webvh:0.5`, `fastResolve` is ignored and not forwarded.
*
* @param did The DID to resolve.
* @param options Optional resolver settings.
* @returns The resolved DID result with resolution metadata and controlled status.
*/
export const resolveDID = async (did: string, options: ResolutionOptions & { witnessProofs?: WitnessProofFileEntry[] } = {}) => {
const activeDIDs = await getActiveDIDs();
const controlled = activeDIDs.includes(did);
// Extract the expected SCID from the DID string so the resolver can
// verify the log's SCID matches what the DID claims.
const didParts = did.split(':');
const scid = (didParts.length > 2 && didParts[0] === 'did' && didParts[1] === 'webvh')
? didParts[2] : undefined;
try {
const log = await fetchLogFromIdentifier(did, controlled);
const version = getWebvhVersionFromLog(log);
const { fastResolve, ...baseOptions } = options;
const optsWithScid = { ...baseOptions, scid };
const result = version === '0.5'
? await v0_5.resolveDIDFromLog(log, optsWithScid)
: await v1.resolveDIDFromLog(log, { ...optsWithScid, fastResolve });
maybeWriteTestLog(result.did, log);
return { ...result, controlled };
} catch (e: any) {
let errorType: DidResolutionError = DidResolutionError.InvalidDid;
const message = e instanceof Error ? e.message : String(e);
if (/not found/i.test(message) || /404/.test(message)) {
errorType = DidResolutionError.NotFound;
}
return {
did,
doc: null,
meta: {
error: errorType,
problemDetails: {
type: errorType === DidResolutionError.NotFound
? 'https://w3id.org/security#NOT_FOUND'
: 'https://w3id.org/security#INVALID_CONTROLLED_IDENTIFIER_DOCUMENT_ID',
title: errorType === DidResolutionError.NotFound
? 'The DID Log or resource was not found.'
: 'The resolved DID is invalid.',
detail: message
}
},
controlled
};
}
};
/**
* Resolves a DID from an in-memory DID log.
*
* For `did:webvh:1.0`, `fastResolve` is forwarded to the v1 resolver.
* For `did:webvh:0.5`, `fastResolve` is ignored and not forwarded.
*
* @param log In-memory DID log entries.
* @param options Optional resolver settings.
* @returns The resolved DID result with resolution metadata.
*/
export const resolveDIDFromLog = async (log: DIDLog, options: ResolutionOptions & { witnessProofs?: WitnessProofFileEntry[] } = {}) => {
const version = getWebvhVersionFromLog(log);
const { fastResolve, ...baseOptions } = options;
if (version === '0.5') {
const result = await v0_5.resolveDIDFromLog(log, baseOptions);
maybeWriteTestLog(result.did, log);
return result;
}
const result = await v1.resolveDIDFromLog(log, { ...baseOptions, fastResolve });
maybeWriteTestLog(result.did, log);
return result;
};
/**
* Updates an existing DID log with a new entry.
*
* @param options DID update options.
* @returns The updated DID, resolved document, and DID log.
*/
export const updateDID = async (options: UpdateDIDInterface & { services?: any[], domain?: string, updated?: string }): Promise<UpdateDIDResult> => {
const version = options.log ? getWebvhVersionFromLog(options.log) : getWebvhVersionFromOptions(options);
const result = version === '0.5'
? await v0_5.updateDID(options)
: await v1.updateDID(options);
maybeWriteTestLog(result.did, result.log);
return result;
};
/**
* Deactivates an existing DID by appending a deactivation entry.
*
* @param options DID deactivation options.
* @returns The deactivated DID result and updated DID log.
*/
export const deactivateDID = async (options: DeactivateDIDInterface & { updateKeys?: string[] }) => {
const version = options.log ? getWebvhVersionFromLog(options.log) : getWebvhVersionFromOptions(options);
const result = version === '0.5'
? await v0_5.deactivateDID(options)
: await v1.deactivateDID(options);
maybeWriteTestLog(result.did, result.log);
return result;
};