@nuwa-ai/identity-kit
Version:
SDK for NIP-1 Agent Single DID Multi-Key Model and NIP-3 CADOP (Custodian-Assisted DID Onboarding Protocol)
1,438 lines (1,426 loc) • 181 kB
JavaScript
var __defProp = Object.defineProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
// src/errors/IdentityKitError.ts
var IdentityKitErrorCode = /* @__PURE__ */ ((IdentityKitErrorCode2) => {
IdentityKitErrorCode2["INVALID_CONFIGURATION"] = "INVALID_CONFIGURATION";
IdentityKitErrorCode2["ENVIRONMENT_NOT_SUPPORTED"] = "ENVIRONMENT_NOT_SUPPORTED";
IdentityKitErrorCode2["INITIALIZATION_FAILED"] = "INITIALIZATION_FAILED";
IdentityKitErrorCode2["DID_NOT_FOUND"] = "DID_NOT_FOUND";
IdentityKitErrorCode2["DID_INVALID_FORMAT"] = "DID_INVALID_FORMAT";
IdentityKitErrorCode2["DID_METHOD_NOT_SUPPORTED"] = "DID_METHOD_NOT_SUPPORTED";
IdentityKitErrorCode2["DID_CREATION_FAILED"] = "DID_CREATION_FAILED";
IdentityKitErrorCode2["DID_RESOLUTION_FAILED"] = "DID_RESOLUTION_FAILED";
IdentityKitErrorCode2["DID_NOT_SET"] = "DID_NOT_SET";
IdentityKitErrorCode2["DID_SERVICE_NOT_FOUND"] = "DID_SERVICE_NOT_FOUND";
IdentityKitErrorCode2["DID_VERIFICATION_METHOD_NOT_FOUND"] = "DID_VERIFICATION_METHOD_NOT_FOUND";
IdentityKitErrorCode2["VDR_NOT_AVAILABLE"] = "VDR_NOT_AVAILABLE";
IdentityKitErrorCode2["VDR_OPERATION_FAILED"] = "VDR_OPERATION_FAILED";
IdentityKitErrorCode2["VDR_NETWORK_ERROR"] = "VDR_NETWORK_ERROR";
IdentityKitErrorCode2["VDR_INVALID_RESPONSE"] = "VDR_INVALID_RESPONSE";
IdentityKitErrorCode2["KEY_NOT_FOUND"] = "KEY_NOT_FOUND";
IdentityKitErrorCode2["KEY_INVALID_FORMAT"] = "KEY_INVALID_FORMAT";
IdentityKitErrorCode2["KEY_GENERATION_FAILED"] = "KEY_GENERATION_FAILED";
IdentityKitErrorCode2["KEY_IMPORT_FAILED"] = "KEY_IMPORT_FAILED";
IdentityKitErrorCode2["KEY_STORAGE_ERROR"] = "KEY_STORAGE_ERROR";
IdentityKitErrorCode2["KEY_PERMISSION_DENIED"] = "KEY_PERMISSION_DENIED";
IdentityKitErrorCode2["KEY_VALIDATION_FAILED"] = "KEY_VALIDATION_FAILED";
IdentityKitErrorCode2["KEY_PRIVATE_KEY_NOT_AVAILABLE"] = "KEY_PRIVATE_KEY_NOT_AVAILABLE";
IdentityKitErrorCode2["KEY_DID_MISMATCH"] = "KEY_DID_MISMATCH";
IdentityKitErrorCode2["KEY_ID_MISMATCH"] = "KEY_ID_MISMATCH";
IdentityKitErrorCode2["KEY_TYPE_NOT_SUPPORTED"] = "KEY_TYPE_NOT_SUPPORTED";
IdentityKitErrorCode2["KEY_ALREADY_EXISTS"] = "KEY_ALREADY_EXISTS";
IdentityKitErrorCode2["SIGNING_FAILED"] = "SIGNING_FAILED";
IdentityKitErrorCode2["SIGNATURE_VERIFICATION_FAILED"] = "SIGNATURE_VERIFICATION_FAILED";
IdentityKitErrorCode2["SIGNER_NOT_AVAILABLE"] = "SIGNER_NOT_AVAILABLE";
IdentityKitErrorCode2["SIGNER_INVALID_DID"] = "SIGNER_INVALID_DID";
IdentityKitErrorCode2["SIGNER_NO_KEYS"] = "SIGNER_NO_KEYS";
IdentityKitErrorCode2["AUTH_INVALID_HEADER"] = "AUTH_INVALID_HEADER";
IdentityKitErrorCode2["AUTH_INVALID_BASE64"] = "AUTH_INVALID_BASE64";
IdentityKitErrorCode2["AUTH_INVALID_JSON"] = "AUTH_INVALID_JSON";
IdentityKitErrorCode2["AUTH_MISSING_SIGNATURE"] = "AUTH_MISSING_SIGNATURE";
IdentityKitErrorCode2["AUTH_TIMESTAMP_OUT_OF_WINDOW"] = "AUTH_TIMESTAMP_OUT_OF_WINDOW";
IdentityKitErrorCode2["AUTH_NONCE_REPLAYED"] = "AUTH_NONCE_REPLAYED";
IdentityKitErrorCode2["AUTH_DID_DOCUMENT_NOT_FOUND"] = "AUTH_DID_DOCUMENT_NOT_FOUND";
IdentityKitErrorCode2["AUTH_VERIFICATION_METHOD_NOT_FOUND"] = "AUTH_VERIFICATION_METHOD_NOT_FOUND";
IdentityKitErrorCode2["AUTH_INVALID_PUBLIC_KEY"] = "AUTH_INVALID_PUBLIC_KEY";
IdentityKitErrorCode2["AUTH_DID_MISMATCH"] = "AUTH_DID_MISMATCH";
IdentityKitErrorCode2["WEB_BROWSER_NOT_SUPPORTED"] = "WEB_BROWSER_NOT_SUPPORTED";
IdentityKitErrorCode2["WEB_STORAGE_NOT_AVAILABLE"] = "WEB_STORAGE_NOT_AVAILABLE";
IdentityKitErrorCode2["WEB_DEEPLINK_FAILED"] = "WEB_DEEPLINK_FAILED";
IdentityKitErrorCode2["WEB_CADOP_CONNECTION_FAILED"] = "WEB_CADOP_CONNECTION_FAILED";
IdentityKitErrorCode2["WEB_OAUTH_CALLBACK_FAILED"] = "WEB_OAUTH_CALLBACK_FAILED";
IdentityKitErrorCode2["WEB_NOT_CONNECTED"] = "WEB_NOT_CONNECTED";
IdentityKitErrorCode2["WEB_CALLBACK_FAILED"] = "WEB_CALLBACK_FAILED";
IdentityKitErrorCode2["REACT_NOT_AVAILABLE"] = "REACT_NOT_AVAILABLE";
IdentityKitErrorCode2["REACT_HOOK_MISUSE"] = "REACT_HOOK_MISUSE";
IdentityKitErrorCode2["CRYPTO_PROVIDER_NOT_FOUND"] = "CRYPTO_PROVIDER_NOT_FOUND";
IdentityKitErrorCode2["CRYPTO_OPERATION_FAILED"] = "CRYPTO_OPERATION_FAILED";
IdentityKitErrorCode2["CRYPTO_KEY_DERIVATION_FAILED"] = "CRYPTO_KEY_DERIVATION_FAILED";
IdentityKitErrorCode2["MULTIBASE_DECODE_FAILED"] = "MULTIBASE_DECODE_FAILED";
IdentityKitErrorCode2["MULTIBASE_ENCODE_FAILED"] = "MULTIBASE_ENCODE_FAILED";
IdentityKitErrorCode2["MULTIBASE_INVALID_FORMAT"] = "MULTIBASE_INVALID_FORMAT";
IdentityKitErrorCode2["SCOPE_VALIDATION_FAILED"] = "SCOPE_VALIDATION_FAILED";
IdentityKitErrorCode2["SCOPE_INVALID_FORMAT"] = "SCOPE_INVALID_FORMAT";
IdentityKitErrorCode2["VALIDATION_FAILED"] = "VALIDATION_FAILED";
IdentityKitErrorCode2["INVALID_INPUT_FORMAT"] = "INVALID_INPUT_FORMAT";
IdentityKitErrorCode2["DEEPLINK_INVALID_STATE"] = "DEEPLINK_INVALID_STATE";
IdentityKitErrorCode2["DEEPLINK_CALLBACK_FAILED"] = "DEEPLINK_CALLBACK_FAILED";
IdentityKitErrorCode2["STORAGE_QUOTA_EXCEEDED"] = "STORAGE_QUOTA_EXCEEDED";
IdentityKitErrorCode2["STORAGE_OPERATION_FAILED"] = "STORAGE_OPERATION_FAILED";
IdentityKitErrorCode2["SIGNER_CONVERSION_FAILED"] = "SIGNER_CONVERSION_FAILED";
IdentityKitErrorCode2["SIGNER_OPERATION_FAILED"] = "SIGNER_OPERATION_FAILED";
IdentityKitErrorCode2["PERMISSION_DENIED"] = "PERMISSION_DENIED";
IdentityKitErrorCode2["OPERATION_NOT_PERMITTED"] = "OPERATION_NOT_PERMITTED";
IdentityKitErrorCode2["OPERATION_NOT_SUPPORTED"] = "OPERATION_NOT_SUPPORTED";
IdentityKitErrorCode2["INVALID_PARAMETER"] = "INVALID_PARAMETER";
IdentityKitErrorCode2["INTERNAL_ERROR"] = "INTERNAL_ERROR";
IdentityKitErrorCode2["NETWORK_ERROR"] = "NETWORK_ERROR";
IdentityKitErrorCode2["TIMEOUT_ERROR"] = "TIMEOUT_ERROR";
return IdentityKitErrorCode2;
})(IdentityKitErrorCode || {});
var IdentityKitError = class extends Error {
constructor(code, message, options) {
super(message);
this.name = "IdentityKitError";
this.code = code;
this.category = options?.category || this.inferCategory(code);
this.details = options?.details;
this.cause = options?.cause;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
if (options?.cause) {
this.stack = `${this.stack}
Caused by: ${options.cause.stack}`;
}
}
/**
* Infer error category from error code
*/
inferCategory(code) {
if (code.startsWith("AUTH_")) return "authentication";
if (code.startsWith("DID_")) return "did";
if (code.startsWith("VDR_")) return "vdr";
if (code.startsWith("KEY_")) return "key-management";
if (code.startsWith("WEB_")) return "web";
if (code.startsWith("REACT_")) return "react";
if (code.startsWith("CRYPTO_")) return "crypto";
if (code.startsWith("MULTIBASE_")) return "multibase";
if (code.startsWith("SCOPE_") || code.startsWith("VALIDATION_")) return "validation";
if (code.startsWith("DEEPLINK_")) return "deeplink";
if (code.startsWith("STORAGE_")) return "storage";
if (code.startsWith("SIGNER_")) return "signer";
if (code.includes("SIGNING") || code.includes("SIGNATURE")) return "signing";
if (code.includes("NETWORK")) return "network";
if (code.includes("PERMISSION")) return "permission";
return "general";
}
/**
* Convert to a plain object for serialization
*/
toJSON() {
return {
name: this.name,
code: this.code,
category: this.category,
message: this.message,
details: this.details,
stack: this.stack
};
}
/**
* Get a user-friendly error message with suggestions
*/
getUserMessage() {
const suggestions = this.getSuggestions();
let message = this.message;
if (suggestions.length > 0) {
message += "\n\nSuggestions:\n" + suggestions.map((s) => `\u2022 ${s}`).join("\n");
}
return message;
}
/**
* Get contextual suggestions based on error code
*/
getSuggestions() {
switch (this.code) {
case "WEB_BROWSER_NOT_SUPPORTED" /* WEB_BROWSER_NOT_SUPPORTED */:
return [
"Use a modern browser that supports required Web APIs",
"Check if you're running in a browser environment"
];
case "WEB_STORAGE_NOT_AVAILABLE" /* WEB_STORAGE_NOT_AVAILABLE */:
return [
"Enable localStorage or IndexedDB in your browser",
"Check if you're in private/incognito mode",
"Consider using memory storage as fallback"
];
case "DID_METHOD_NOT_SUPPORTED" /* DID_METHOD_NOT_SUPPORTED */:
return [
"Check if the DID method is registered with VDRRegistry",
"Verify the DID format is correct"
];
case "VDR_NETWORK_ERROR" /* VDR_NETWORK_ERROR */:
return [
"Check your network connection",
"Verify the RPC URL is correct and accessible",
"Check if the VDR service is running"
];
case "KEY_STORAGE_ERROR" /* KEY_STORAGE_ERROR */:
return [
"Check browser storage permissions",
"Verify storage quota is not exceeded",
"Try clearing browser storage and retry"
];
case "REACT_NOT_AVAILABLE" /* REACT_NOT_AVAILABLE */:
return [
"Ensure React is properly installed and imported",
"Check if you're using the hook in a React component"
];
case "CRYPTO_PROVIDER_NOT_FOUND" /* CRYPTO_PROVIDER_NOT_FOUND */:
return [
"Check if the key type is supported",
"Verify the crypto provider factory configuration"
];
case "MULTIBASE_DECODE_FAILED" /* MULTIBASE_DECODE_FAILED */:
return [
"Verify the encoded string format is correct",
"Check if the multibase prefix is valid",
"Ensure the input is not corrupted"
];
case "SCOPE_VALIDATION_FAILED" /* SCOPE_VALIDATION_FAILED */:
return [
"Check the scope format: address::module::function",
"Verify the address format is valid",
"Ensure module and function names are correct"
];
case "DEEPLINK_INVALID_STATE" /* DEEPLINK_INVALID_STATE */:
return [
"Check if the state parameter matches the stored value",
"Verify the callback URL parameters are correct",
"Ensure the session storage is available"
];
case "STORAGE_QUOTA_EXCEEDED" /* STORAGE_QUOTA_EXCEEDED */:
return [
"Clear unused data from browser storage",
"Check available storage quota",
"Consider using a different storage strategy"
];
case "SIGNER_CONVERSION_FAILED" /* SIGNER_CONVERSION_FAILED */:
return [
"Verify the signer implements the required interface",
"Check if the key ID is available in the signer",
"Ensure the DID account signer is properly configured"
];
default:
return [];
}
}
};
function createConfigurationError(message, details, cause) {
return new IdentityKitError("INVALID_CONFIGURATION" /* INVALID_CONFIGURATION */, message, {
category: "configuration",
details,
cause
});
}
function createDIDError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "did",
details,
cause
});
}
function createVDRError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "vdr",
details,
cause
});
}
function createKeyManagementError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "key-management",
details,
cause
});
}
function createAuthenticationError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "authentication",
details,
cause
});
}
function createWebError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "web",
details,
cause
});
}
function createReactError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "react",
details,
cause
});
}
function createCryptoError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "crypto",
details,
cause
});
}
function createMultibaseError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "multibase",
details,
cause
});
}
function createStorageError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "storage",
details,
cause
});
}
function createValidationError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "validation",
details,
cause
});
}
function createSignerError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "signer",
details,
cause
});
}
function createDeepLinkError(code, message, details, cause) {
return new IdentityKitError(code, message, {
category: "deeplink",
details,
cause
});
}
function wrapUnknownError(error, context, code = "INTERNAL_ERROR" /* INTERNAL_ERROR */) {
const originalError = error instanceof Error ? error : new Error(String(error));
return new IdentityKitError(code, `${context}: ${originalError.message}`, {
cause: originalError,
details: { context }
});
}
function isIdentityKitError(error) {
return error instanceof IdentityKitError;
}
var AuthErrorCodeMapping = {
INVALID_HEADER: "AUTH_INVALID_HEADER" /* AUTH_INVALID_HEADER */,
INVALID_BASE64: "AUTH_INVALID_BASE64" /* AUTH_INVALID_BASE64 */,
INVALID_JSON: "AUTH_INVALID_JSON" /* AUTH_INVALID_JSON */,
MISSING_SIGNATURE: "AUTH_MISSING_SIGNATURE" /* AUTH_MISSING_SIGNATURE */,
TIMESTAMP_OUT_OF_WINDOW: "AUTH_TIMESTAMP_OUT_OF_WINDOW" /* AUTH_TIMESTAMP_OUT_OF_WINDOW */,
NONCE_REPLAYED: "AUTH_NONCE_REPLAYED" /* AUTH_NONCE_REPLAYED */,
SIGNATURE_VERIFICATION_FAILED: "SIGNATURE_VERIFICATION_FAILED" /* SIGNATURE_VERIFICATION_FAILED */,
DID_DOCUMENT_NOT_FOUND: "AUTH_DID_DOCUMENT_NOT_FOUND" /* AUTH_DID_DOCUMENT_NOT_FOUND */,
VERIFICATION_METHOD_NOT_FOUND: "AUTH_VERIFICATION_METHOD_NOT_FOUND" /* AUTH_VERIFICATION_METHOD_NOT_FOUND */,
INVALID_PUBLIC_KEY: "AUTH_INVALID_PUBLIC_KEY" /* AUTH_INVALID_PUBLIC_KEY */,
DID_MISMATCH: "AUTH_DID_MISMATCH" /* AUTH_DID_MISMATCH */
};
// src/types/crypto.ts
var KeyType = /* @__PURE__ */ ((KeyType7) => {
KeyType7["ED25519"] = "Ed25519VerificationKey2020";
KeyType7["SECP256K1"] = "EcdsaSecp256k1VerificationKey2019";
KeyType7["ECDSAR1"] = "EcdsaSecp256r1VerificationKey2019";
return KeyType7;
})(KeyType || {});
var KEY_TYPE = KeyType;
function isKeyType(value) {
return Object.values(KeyType).includes(value);
}
function toKeyType(value) {
if (isKeyType(value)) {
return value;
}
throw createValidationError(
"KEY_TYPE_NOT_SUPPORTED" /* KEY_TYPE_NOT_SUPPORTED */,
`Invalid key type: ${value}`,
{ value, supportedTypes: Object.values(KeyType) }
);
}
function roochSignatureSchemeToKeyType(scheme) {
if (scheme === "Secp256k1") {
return "EcdsaSecp256k1VerificationKey2019" /* SECP256K1 */;
} else if (scheme === "ED25519") {
return "Ed25519VerificationKey2020" /* ED25519 */;
} else if (scheme === "EcdsaR1") {
return "EcdsaSecp256r1VerificationKey2019" /* ECDSAR1 */;
}
throw createValidationError(
"KEY_TYPE_NOT_SUPPORTED" /* KEY_TYPE_NOT_SUPPORTED */,
`Unsupported Rooch signature scheme: ${scheme}`,
{ scheme, supportedSchemes: ["Secp256k1", "ED25519", "EcdsaR1"] }
);
}
function keyTypeToRoochSignatureScheme(keyType) {
if (keyType === "EcdsaSecp256k1VerificationKey2019" /* SECP256K1 */) {
return "Secp256k1";
} else if (keyType === "Ed25519VerificationKey2020" /* ED25519 */) {
return "ED25519";
} else if (keyType === "EcdsaSecp256r1VerificationKey2019" /* ECDSAR1 */) {
return "EcdsaR1";
}
throw createValidationError(
"KEY_TYPE_NOT_SUPPORTED" /* KEY_TYPE_NOT_SUPPORTED */,
`Unsupported key type: ${keyType}`,
{ keyType, supportedTypes: Object.values(KeyType) }
);
}
function algorithmToKeyType(algorithm) {
switch (algorithm) {
case -8:
return "Ed25519VerificationKey2020" /* ED25519 */;
case -7:
return "EcdsaSecp256r1VerificationKey2019" /* ECDSAR1 */;
default:
return void 0;
}
}
function keyTypeToAlgorithm(keyType) {
switch (keyType) {
case "Ed25519VerificationKey2020" /* ED25519 */:
return -8;
case "EcdsaSecp256r1VerificationKey2019" /* ECDSAR1 */:
return -7;
default:
return void 0;
}
}
function getSupportedAlgorithms() {
return [-8, -7];
}
// src/cache/InMemoryLRUDIDDocumentCache.ts
var InMemoryLRUDIDDocumentCache = class {
constructor(maxEntries = 1e3) {
this.capacity = maxEntries;
this.map = /* @__PURE__ */ new Map();
}
get(did) {
if (!this.map.has(did)) return void 0;
const value = this.map.get(did) ?? null;
this.map.delete(did);
this.map.set(did, value);
return value;
}
set(did, doc) {
if (this.map.has(did)) {
this.map.delete(did);
} else if (this.map.size >= this.capacity) {
const lruKey = this.map.keys().next().value;
if (lruKey !== void 0) {
this.map.delete(lruKey);
}
}
this.map.set(did, doc);
}
has(did) {
return this.map.has(did);
}
delete(did) {
this.map.delete(did);
}
clear() {
this.map.clear();
}
};
// src/vdr/VDRRegistry.ts
var VDRRegistry = class _VDRRegistry {
constructor() {
this.vdrs = /* @__PURE__ */ new Map();
this.cache = new InMemoryLRUDIDDocumentCache();
}
static getInstance() {
if (!this.instance) {
this.instance = new _VDRRegistry();
}
return this.instance;
}
/** Register a VDR implementation for its DID method (e.g., 'key', 'rooch'). */
registerVDR(vdr) {
this.vdrs.set(vdr.getMethod(), vdr);
}
/** Retrieve a previously registered VDR implementation by its method. */
getVDR(method) {
return this.vdrs.get(method);
}
/**
* Override the default cache implementation.
* This allows developers to provide their own cache (e.g., Redis, browser storage).
*/
setCache(cache) {
this.cache = cache;
}
/** Returns the currently configured cache instance. */
getCache() {
return this.cache;
}
async resolveDID(did, options) {
const method = did.split(":")[1];
const vdr = this.vdrs.get(method);
if (!vdr) {
throw createVDRError(
"VDR_NOT_AVAILABLE" /* VDR_NOT_AVAILABLE */,
`No VDR available for method: ${method}`,
{ method, availableMethods: Array.from(this.vdrs.keys()) }
);
}
if (!options?.forceRefresh) {
const cached = this.cache.get(did);
if (cached !== void 0) {
return cached;
}
}
const resolved = await vdr.resolve(did);
this.cache.set(did, resolved);
return resolved;
}
async createDID(method, creationRequest, options) {
const vdr = this.vdrs.get(method);
if (!vdr) {
throw createVDRError(
"VDR_NOT_AVAILABLE" /* VDR_NOT_AVAILABLE */,
`No VDR available for method: ${method}`,
{ method, availableMethods: Array.from(this.vdrs.keys()) }
);
}
const result = await vdr.create(creationRequest, options);
if (result.success && result.didDocument) {
this.cache.set(result.didDocument.id, result.didDocument);
}
return result;
}
async createDIDViaCADOP(method, creationRequest, options) {
const vdr = this.vdrs.get(method);
if (!vdr) {
throw createVDRError(
"VDR_NOT_AVAILABLE" /* VDR_NOT_AVAILABLE */,
`No VDR available for method: ${method}`,
{ method, availableMethods: Array.from(this.vdrs.keys()) }
);
}
const result = await vdr.createViaCADOP(creationRequest, options);
if (result.success && result.didDocument) {
this.cache.set(result.didDocument.id, result.didDocument);
}
return result;
}
async createDIDViaCADOPWithController(method, creationRequest, options) {
const vdr = this.vdrs.get(method);
if (!vdr) {
throw createVDRError(
"VDR_NOT_AVAILABLE" /* VDR_NOT_AVAILABLE */,
`No VDR available for method: ${method}`,
{ method, availableMethods: Array.from(this.vdrs.keys()) }
);
}
const result = await vdr.createViaCADOPWithController(creationRequest, options);
if (result.success && result.didDocument) {
this.cache.set(result.didDocument.id, result.didDocument);
}
return result;
}
async exists(did) {
const method = did.split(":")[1];
const vdr = this.vdrs.get(method);
if (!vdr) {
throw createVDRError(
"VDR_NOT_AVAILABLE" /* VDR_NOT_AVAILABLE */,
`No VDR available for method: ${method}`,
{ method, availableMethods: Array.from(this.vdrs.keys()) }
);
}
if (this.cache.has(did)) {
const doc = this.cache.get(did);
return doc !== null;
}
const exists = await vdr.exists(did);
return exists;
}
};
// src/multibase/base.ts
import { base58btc } from "multiformats/bases/base58";
import { base64pad, base64, base64url, base64urlpad } from "multiformats/bases/base64";
import { base16 } from "multiformats/bases/base16";
// src/utils/bytes.ts
function stringToBytes(str) {
if (typeof TextEncoder !== "undefined") {
return new TextEncoder().encode(str);
}
if (typeof Buffer !== "undefined" && typeof Buffer.from === "function") {
return Uint8Array.from(Buffer.from(str, "utf-8"));
}
throw createValidationError(
"ENVIRONMENT_NOT_SUPPORTED" /* ENVIRONMENT_NOT_SUPPORTED */,
"No TextEncoder or Buffer available in this environment.",
{
environment: typeof globalThis,
textEncoderAvailable: typeof TextEncoder !== "undefined",
bufferAvailable: typeof Buffer !== "undefined"
}
);
}
function bytesToString(bytes) {
if (typeof TextDecoder !== "undefined") {
return new TextDecoder("utf-8").decode(bytes);
}
if (typeof Buffer !== "undefined" && typeof Buffer.from === "function") {
return Buffer.from(bytes).toString("utf-8");
}
throw createValidationError(
"ENVIRONMENT_NOT_SUPPORTED" /* ENVIRONMENT_NOT_SUPPORTED */,
"No TextDecoder or Buffer available in this environment.",
{
environment: typeof globalThis,
textDecoderAvailable: typeof TextDecoder !== "undefined",
bufferAvailable: typeof Buffer !== "undefined"
}
);
}
function base64urlToBytes(base64url2) {
const padding = base64url2.length % 4;
const paddedBase64url = base64url2 + "=".repeat(padding === 0 ? 0 : 4 - padding);
const base642 = paddedBase64url.replace(/-/g, "+").replace(/_/g, "/");
const binaryString = atob(base642);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes;
}
var Bytes = {
stringToBytes,
bytesToString,
base64urlToBytes
};
// src/multibase/base.ts
var ENCODER_MAP = {
base58btc,
base64pad,
base64,
base64url,
base64urlpad,
base16
};
var MultibaseCodec = class {
/**
* Generic encode
* Example: `MultibaseCodec.encode(bytes, 'base64url')`
*/
static encode(data, base) {
const encoder = ENCODER_MAP[base];
if (!encoder) {
throw createMultibaseError(
"MULTIBASE_ENCODE_FAILED" /* MULTIBASE_ENCODE_FAILED */,
`Unsupported multibase: ${base}`,
{ base, supportedBases: Object.keys(ENCODER_MAP) }
);
}
const bytes = typeof data === "string" ? stringToBytes(data) : data;
return encoder.encode(bytes);
}
/**
* Encode bytes to base58btc format
* @param bytes The bytes to encode
* @returns base58btc encoded string with 'z' prefix
*/
static encodeBase58btc(bytes) {
return this.encode(bytes, "base58btc");
}
/**
* Encode bytes to base64pad format
* @param bytes The bytes to encode
* @returns base64pad encoded string with 'M' prefix
*/
static encodeBase64pad(data) {
return this.encode(data, "base64pad");
}
/**
* Encode bytes to base16 (hex) format
* @param bytes The bytes to encode
* @returns base16 encoded string with 'f' prefix
*/
static encodeBase16(bytes) {
return this.encode(bytes, "base16");
}
/**
* Encode bytes to base64 format
* @param bytes The bytes to encode
* @returns base64 encoded string
*/
static encodeBase64(data) {
return this.encode(data, "base64");
}
/**
* Encode bytes to base64url format (RFC4648 URL-safe, no padding)
* @param bytes The bytes to encode
* @returns base64url encoded string with 'u' prefix
*/
static encodeBase64url(data) {
return this.encode(data, "base64url");
}
/**
* Encode bytes to base64urlpad format (URL-safe with padding)
* @param bytes The bytes to encode
* @returns base64urlpad encoded string with 'U' prefix
*/
static encodeBase64urlpad(data) {
return this.encode(data, "base64urlpad");
}
/**
* Decode base58btc string to bytes
* @param encoded The base58btc encoded string
* @returns decoded bytes
*/
static decodeBase58btc(encoded) {
return base58btc.decode(encoded);
}
/**
* Decode base64pad string to bytes
* @param encoded The base64pad encoded string
* @returns decoded bytes
*/
static decodeBase64pad(encoded) {
return base64pad.decode(encoded);
}
/**
* Decode base16 string to bytes
* @param encoded The base16 encoded string
* @returns decoded bytes
*/
static decodeBase16(encoded) {
return base16.decode(encoded);
}
/**
* Decode base64 string to bytes
* @param encoded The base64 encoded string
* @returns decoded bytes
*/
static decodeBase64(encoded) {
return base64.decode(encoded);
}
/**
* Decode base64url string to bytes
* @param encoded The base64url encoded string
* @returns decoded bytes
*/
static decodeBase64url(encoded) {
return base64url.decode(encoded);
}
/**
* Decode base64url string to string
* @param encoded The base64url encoded string
* @returns decoded string
*/
static decodeBase64urlToString(encoded) {
return bytesToString(this.decodeBase64url(encoded));
}
/**
* Decode base64urlpad string to bytes
* @param encoded The base64urlpad encoded string
* @returns decoded bytes
*/
static decodeBase64urlpad(encoded) {
return base64urlpad.decode(encoded);
}
/**
* Decode base64urlpad string to string
* @param encoded The base64urlpad encoded string
* @returns decoded string
*/
static decodeBase64urlpadToString(encoded) {
return bytesToString(this.decodeBase64urlpad(encoded));
}
/**
* Decode multibase encoded string to bytes
* After multiformats v9, there is no longer a single "universal base" object;
* the official recommendation is to manually dispatch prefixes between the few *.decoder objects you use.
* @param encoded The multibase encoded string
* @returns decoded bytes
*/
static decode(encoded) {
const prefix = encoded[0];
switch (prefix) {
case "z":
return base58btc.decode(encoded);
case "M":
return base64pad.decode(encoded);
case "f":
return base16.decode(encoded);
case "m":
return base64.decode(encoded);
case "u":
return base64url.decode(encoded);
case "U":
return base64urlpad.decode(encoded);
default:
throw createMultibaseError(
"MULTIBASE_DECODE_FAILED" /* MULTIBASE_DECODE_FAILED */,
`Unsupported multibase prefix: ${prefix}`,
{ prefix, supportedPrefixes: ["z", "M", "m", "u", "U", "f"] }
);
}
}
};
// src/multibase/key.ts
var KeyMultibaseCodec = class {
/**
* Encode public key with multicodec prefix
* @param bytes The public key bytes
* @param keyType The key type
* @returns multibase encoded string
*/
static encodeWithType(bytes, keyType) {
const expectedLength = this.getExpectedKeyLength(keyType);
if (bytes.length !== expectedLength) {
throw createValidationError(
"INVALID_INPUT_FORMAT" /* INVALID_INPUT_FORMAT */,
`Invalid key length for ${keyType}. Expected ${expectedLength} bytes, got ${bytes.length}`,
{ keyType, expectedLength, actualLength: bytes.length }
);
}
const prefix = this.getMulticodecPrefix(keyType);
const prefixedKey = this.concatenateBytes(prefix, bytes);
return MultibaseCodec.encodeBase58btc(prefixedKey);
}
/**
* Decode multibase encoded key
* @param encoded The multibase encoded string
* @returns The key type and public key bytes
*/
static decodeWithType(encoded) {
try {
const decoded = MultibaseCodec.decodeBase58btc(encoded);
if (decoded.length < 2) {
throw createMultibaseError(
"MULTIBASE_DECODE_FAILED" /* MULTIBASE_DECODE_FAILED */,
"Invalid key format: too short",
{ encoded, minimumLength: 2, actualLength: decoded.length }
);
}
const keyType = this.extractKeyType(decoded);
const bytes = this.extractBytes(decoded);
const expectedLength = this.getExpectedKeyLength(keyType);
if (bytes.length !== expectedLength) {
throw createValidationError(
"INVALID_INPUT_FORMAT" /* INVALID_INPUT_FORMAT */,
`Invalid key length for ${keyType}. Expected ${expectedLength} bytes, got ${bytes.length}`,
{ keyType, expectedLength, actualLength: bytes.length }
);
}
return { keyType, bytes };
} catch (error) {
if (error instanceof Error && error.message === "Non-base58btc character") {
throw createMultibaseError(
"MULTIBASE_DECODE_FAILED" /* MULTIBASE_DECODE_FAILED */,
"Invalid multibase format",
{ encoded }
);
}
throw error;
}
}
static getMulticodecPrefix(keyType) {
switch (keyType) {
case KEY_TYPE.ED25519:
return this.ED25519_PREFIX;
case KEY_TYPE.SECP256K1:
return this.SECP256K1_PREFIX;
case KEY_TYPE.ECDSAR1:
return this.ECDSA_R1_PREFIX;
default:
throw createValidationError(
"KEY_TYPE_NOT_SUPPORTED" /* KEY_TYPE_NOT_SUPPORTED */,
`Unsupported key type: ${keyType}`,
{ keyType, supportedTypes: [KEY_TYPE.ED25519, KEY_TYPE.SECP256K1, KEY_TYPE.ECDSAR1] }
);
}
}
static concatenateBytes(a, b) {
const result = new Uint8Array(a.length + b.length);
result.set(a);
result.set(b, a.length);
return result;
}
static extractKeyType(prefixedBytes) {
if (prefixedBytes[0] === 237 && prefixedBytes[1] === 1) {
return KEY_TYPE.ED25519;
} else if (prefixedBytes[0] === 231 && prefixedBytes[1] === 1) {
return KEY_TYPE.SECP256K1;
} else if (prefixedBytes[0] === 18 && prefixedBytes[1] === 0) {
return KEY_TYPE.ECDSAR1;
}
throw createMultibaseError(
"MULTIBASE_DECODE_FAILED" /* MULTIBASE_DECODE_FAILED */,
"Unknown key type prefix",
{ prefix: Array.from(prefixedBytes.slice(0, 2)) }
);
}
static extractBytes(prefixedBytes) {
return prefixedBytes.slice(2);
}
static getExpectedKeyLength(keyType) {
switch (keyType) {
case KEY_TYPE.ED25519:
return this.ED25519_KEY_LENGTH;
case KEY_TYPE.SECP256K1:
return this.SECP256K1_KEY_LENGTH;
case KEY_TYPE.ECDSAR1:
return this.ECDSA_R1_KEY_LENGTH;
default:
throw createValidationError(
"KEY_TYPE_NOT_SUPPORTED" /* KEY_TYPE_NOT_SUPPORTED */,
`Unsupported key type: ${keyType}`,
{ keyType, supportedTypes: [KEY_TYPE.ED25519, KEY_TYPE.SECP256K1, KEY_TYPE.ECDSAR1] }
);
}
}
};
KeyMultibaseCodec.ED25519_PREFIX = new Uint8Array([237, 1]);
KeyMultibaseCodec.SECP256K1_PREFIX = new Uint8Array([231, 1]);
KeyMultibaseCodec.ECDSA_R1_PREFIX = new Uint8Array([18, 0]);
KeyMultibaseCodec.ED25519_KEY_LENGTH = 32;
KeyMultibaseCodec.SECP256K1_KEY_LENGTH = 33;
KeyMultibaseCodec.ECDSA_R1_KEY_LENGTH = 33;
// src/multibase/did.ts
var DidKeyCodec = class {
/**
* Generate did:key from public key
* @param publicKey The public key bytes
* @param keyType The key type
* @returns did:key identifier
*/
static generateDidKey(publicKey, keyType) {
const multibase = KeyMultibaseCodec.encodeWithType(publicKey, keyType);
return `did:key:${multibase}`;
}
/**
* Parse did:key to get key type and public key
* @param didKey The did:key identifier
* @returns The key type and public key bytes
*/
static parseDidKey(didKey) {
if (!didKey.startsWith("did:key:")) {
throw createDIDError("DID_INVALID_FORMAT" /* DID_INVALID_FORMAT */, "Invalid did:key format", {
didKey,
expectedPrefix: "did:key:"
});
}
const multibase = didKey.substring(8);
const { keyType, bytes } = KeyMultibaseCodec.decodeWithType(multibase);
return { keyType, publicKey: bytes };
}
};
// src/utils/did.ts
function parseDid(did) {
if (!did.startsWith("did:")) {
throw createDIDError("DID_INVALID_FORMAT" /* DID_INVALID_FORMAT */, `Invalid DID: ${did}`, {
did,
reason: 'DID must start with "did:"'
});
}
const afterPrefix = did.slice(4);
const methodEnd = afterPrefix.indexOf(":");
if (methodEnd === -1) {
throw createDIDError(
"DID_INVALID_FORMAT" /* DID_INVALID_FORMAT */,
`Invalid DID \u2013 missing method/identifier separator: ${did}`,
{ did, reason: 'Missing method/identifier separator ":"' }
);
}
const method = afterPrefix.slice(0, methodEnd);
const idPlusFrag = afterPrefix.slice(methodEnd + 1);
if (!method || !idPlusFrag) {
throw createDIDError("DID_INVALID_FORMAT" /* DID_INVALID_FORMAT */, `Invalid DID: ${did}`, {
did,
reason: "Empty method or identifier"
});
}
const hashIdx = idPlusFrag.indexOf("#");
return hashIdx === -1 ? { method, identifier: idPlusFrag } : {
method,
identifier: idPlusFrag.slice(0, hashIdx),
fragment: idPlusFrag.slice(hashIdx + 1)
};
}
function extractMethod(did) {
return parseDid(did).method;
}
function extractIdentifier(did) {
return parseDid(did).identifier;
}
function extractFragment(idOrDid) {
const idx = idOrDid.indexOf("#");
if (idx === -1) {
throw createDIDError(
"DID_INVALID_FORMAT" /* DID_INVALID_FORMAT */,
`No fragment found in ${idOrDid}`,
{ idOrDid, reason: 'Missing fragment separator "#"' }
);
}
return idOrDid.slice(idx + 1);
}
var extractFragmentFromId = extractFragment;
function buildDid(method, identifier) {
return `did:${method}:${identifier}`;
}
function sameDid(a, b) {
const pa = parseDid(a);
const pb = parseDid(b);
return pa.method === pb.method && pa.identifier === pb.identifier;
}
function getDidWithoutFragment(did) {
const { method, identifier } = parseDid(did);
return buildDid(method, identifier);
}
// src/utils/DebugLogger.ts
var LEVEL_ORDER = {
debug: 10,
info: 20,
warn: 30,
error: 40,
silent: 50
};
function detectInitialGlobalLevel() {
if (typeof process !== "undefined" && process.env) {
const envLevel = process.env.NUWA_LOG_LEVEL;
if (envLevel && envLevel in LEVEL_ORDER) return envLevel;
}
if (typeof window !== "undefined" && window.__NUWA_LOG_LEVEL__) {
const envLevel = window.__NUWA_LOG_LEVEL__;
if (envLevel && envLevel in LEVEL_ORDER) return envLevel;
}
return "info";
}
var _DebugLogger = class _DebugLogger {
constructor(namespace) {
this.namespace = namespace;
this.levelOverridden = false;
this.level = _DebugLogger.globalLevel;
}
/** Acquire (or create) a logger for the given namespace. */
static get(namespace) {
if (!_DebugLogger.loggers.has(namespace)) {
_DebugLogger.loggers.set(namespace, new _DebugLogger(namespace));
}
return _DebugLogger.loggers.get(namespace);
}
/** Override global log level at runtime. */
static setGlobalLevel(level) {
_DebugLogger.globalLevel = level;
for (const logger3 of _DebugLogger.loggers.values()) {
if (!logger3.levelOverridden) {
logger3.level = level;
}
}
}
/** Read current global level. */
static getGlobalLevel() {
return _DebugLogger.globalLevel;
}
/** Set default namespace used by static convenience methods. */
static setDefaultNamespace(namespace) {
_DebugLogger.defaultNamespace = namespace;
}
// ---------------------------------------------------------------------------
// Static convenience logging methods
// ---------------------------------------------------------------------------
/**
* Log using the default namespace. Useful when callers don't need per-module loggers.
* Example: DebugLogger.debug('hello')
*/
static debug(...args) {
_DebugLogger.get(_DebugLogger.defaultNamespace).debug(...args);
}
static info(...args) {
_DebugLogger.get(_DebugLogger.defaultNamespace).info(...args);
}
static warn(...args) {
_DebugLogger.get(_DebugLogger.defaultNamespace).warn(...args);
}
static error(...args) {
_DebugLogger.get(_DebugLogger.defaultNamespace).error(...args);
}
/** Override level for this logger only. */
setLevel(level) {
this.level = level;
this.levelOverridden = true;
}
// -------------------------------------------------------
// Logging helpers
// -------------------------------------------------------
debug(...args) {
this._log("debug", args);
}
info(...args) {
this._log("info", args);
}
warn(...args) {
this._log("warn", args);
}
error(...args) {
this._log("error", args);
}
// prettier-ignore
_log(level, args) {
if (LEVEL_ORDER[level] < LEVEL_ORDER[this.level]) {
return;
}
const prefix = `[${this.namespace}]`;
switch (level) {
case "debug":
console.debug(prefix, ...args);
break;
case "info":
console.info(prefix, ...args);
break;
case "warn":
console.warn(prefix, ...args);
break;
case "error":
console.error(prefix, ...args);
break;
}
}
};
// ---------------------------------------------------------------------------
// Static section
// ---------------------------------------------------------------------------
_DebugLogger.globalLevel = detectInitialGlobalLevel();
_DebugLogger.loggers = /* @__PURE__ */ new Map();
_DebugLogger.defaultNamespace = "global";
var DebugLogger = _DebugLogger;
// src/vdr/abstractVDR.ts
var logger = DebugLogger.get("AbstractVDR");
var AbstractVDR = class {
/**
* Creates a new AbstractVDR instance
*
* @param method The DID method this VDR handles
*/
constructor(method) {
this.method = method;
}
/**
* Gets the DID method this VDR handles
*
* @returns The DID method string
*/
getMethod() {
return this.method;
}
/**
* Validates that a given DID matches the method this VDR handles
*
* @param did The DID to validate
* @throws Error if the DID doesn't match this VDR's method
*/
validateDIDMethod(did) {
const parsedDid = parseDid(did);
if (parsedDid.method !== this.method) {
throw createDIDError(
"DID_INVALID_FORMAT" /* DID_INVALID_FORMAT */,
`DID ${did} is not a valid did:${this.method} identifier`,
{ did, expectedMethod: this.method, actualMethod: parsedDid.method }
);
}
}
/**
* Validates a DID document's basic structure
*
* @param document The DID document to validate
* @returns true if valid, throws an error otherwise
*/
validateDocument(document) {
if (!document.id) {
throw createValidationError(
"VALIDATION_FAILED" /* VALIDATION_FAILED */,
"DID document must have an id",
{ document }
);
}
this.validateDIDMethod(document.id);
if (!document["@context"]) {
throw createValidationError(
"VALIDATION_FAILED" /* VALIDATION_FAILED */,
"DID document must have a @context property",
{ document }
);
}
if (!document.verificationMethod || document.verificationMethod.length === 0) {
throw createValidationError(
"VALIDATION_FAILED" /* VALIDATION_FAILED */,
"DID document must have at least one verification method",
{ document }
);
}
return true;
}
/**
* Check if a key has a specific verification relationship in a DID document
*
* @param didDocument The DID document to check
* @param keyId The ID of the verification method
* @param relationship The verification relationship to check
* @returns True if the key has the relationship
*/
hasVerificationRelationship(didDocument, keyId, relationship) {
const relationshipArray = didDocument[relationship];
if (!relationshipArray) return false;
return relationshipArray.some((item) => {
if (typeof item === "string") {
return item === keyId;
} else if (typeof item === "object" && item.id) {
return item.id === keyId;
}
return false;
});
}
/**
* Validates if a key has permission to perform an operation
*
* @param didDocument The DID document
* @param keyId The ID of the key
* @param requiredRelationship The required verification relationship
* @returns True if the key has permission
*/
validateKeyPermission(didDocument, keyId, requiredRelationship) {
const keyExists = didDocument.verificationMethod?.some((vm) => vm.id === keyId);
if (!keyExists) {
logger.error(`Key ${keyId} not found in DID document`);
return false;
}
const isPrimaryKey = didDocument.verificationMethod?.[0]?.id === keyId;
if (isPrimaryKey) {
return true;
}
const hasPermission = didDocument[requiredRelationship]?.includes(keyId);
if (!hasPermission) {
logger.error(`Key ${keyId} does not have ${requiredRelationship} permission`);
return false;
}
return true;
}
/**
* Default create implementation - throws not implemented error for base class
* Subclasses must override this method to provide actual implementation
*/
async create(request, options) {
throw createVDRError(
"OPERATION_NOT_SUPPORTED" /* OPERATION_NOT_SUPPORTED */,
`create method not implemented for ${this.method} VDR`,
{ method: this.method, operation: "create" }
);
}
/**
* Default CADOP implementation - throws not implemented error
*/
async createViaCADOP(request, options) {
throw createVDRError(
"OPERATION_NOT_SUPPORTED" /* OPERATION_NOT_SUPPORTED */,
`createViaCADOP not implemented for ${this.method} VDR`,
{ method: this.method, operation: "createViaCADOP" }
);
}
/**
* Default CADOP with controller implementation - throws not implemented error
*/
async createViaCADOPWithController(request, options) {
throw createVDRError(
"OPERATION_NOT_SUPPORTED" /* OPERATION_NOT_SUPPORTED */,
`createViaCADOPWithController not implemented for ${this.method} VDR`,
{ method: this.method, operation: "createViaCADOPWithController" }
);
}
/**
* Build DID Document from creation request
*/
buildDIDDocumentFromRequest(request) {
const did = request.preferredDID;
const controllerForVM = Array.isArray(request.controller) ? request.controller[0] : request.controller || did;
const verificationMethod = {
id: `${did}#account-key`,
type: request.keyType || "EcdsaSecp256k1VerificationKey2019",
controller: controllerForVM,
publicKeyMultibase: request.publicKeyMultibase
};
const didDocument = {
"@context": ["https://www.w3.org/ns/did/v1"],
id: did,
controller: request.controller ? Array.isArray(request.controller) ? request.controller : [request.controller] : [did],
verificationMethod: [verificationMethod, ...request.additionalVerificationMethods || []],
service: request.initialServices || []
};
const relationships = request.initialRelationships || [
"authentication",
"assertionMethod",
"capabilityInvocation",
"capabilityDelegation"
];
const vmId = verificationMethod.id;
relationships.forEach((rel) => {
if (!didDocument[rel]) {
didDocument[rel] = [];
}
didDocument[rel].push(vmId);
});
return didDocument;
}
/**
* Checks if a DID exists in the registry
* Default implementation tries to resolve and checks if result is not null
*/
async exists(did) {
try {
const doc = await this.resolve(did);
return doc !== null;
} catch (error) {
return false;
}
}
/**
* Add a verification method to a DID document
* Default implementation that should be overridden by specific VDR implementations
*/
async addVerificationMethod(did, verificationMethod, relationships, options) {
throw createVDRError(
"OPERATION_NOT_SUPPORTED" /* OPERATION_NOT_SUPPORTED */,
`addVerificationMethod not implemented for ${this.method} VDR`,
{ method: this.method, operation: "addVerificationMethod" }
);
}
/**
* Remove a verification method from a DID document
* Default implementation that should be overridden by specific VDR implementations
*/
async removeVerificationMethod(did, id, options) {
throw createVDRError(
"OPERATION_NOT_SUPPORTED" /* OPERATION_NOT_SUPPORTED */,
`removeVerificationMethod not implemented for ${this.method} VDR`,
{ method: this.method, operation: "removeVerificationMethod" }
);
}
/**
* Add a service to a DID document
* Default implementation that should be overridden by specific VDR implementations
*/
async addService(did, service, options) {
throw createVDRError(
"OPERATION_NOT_SUPPORTED" /* OPERATION_NOT_SUPPORTED */,
`addService not implemented for ${this.method} VDR`,
{ method: this.method, operation: "addService" }
);
}
/**
* Remove a service from a DID document
* Default implementation that should be overridden by specific VDR implementations
*/
async removeService(did, id, options) {
throw createVDRError(
"OPERATION_NOT_SUPPORTED" /* OPERATION_NOT_SUPPORTED */,
`removeService not implemented for ${this.method} VDR`,
{ method: this.method, operation: "removeService" }
);
}
/**
* Update verification relationships for a verification method
* Default implementation that should be overridden by specific VDR implementations
*/
async updateRelationships(did, id, add, remove, options) {
throw createVDRError(
"OPERATION_NOT_SUPPORTED" /* OPERATION_NOT_SUPPORTED */,
`updateRelationships not implemented for ${this.method} VDR`,
{ method: this.method, operation: "updateRelationships" }
);
}
/**
* Update the controller of a DID document
* Default implementation that should be overridden by specific VDR implementations
*/
async updateController(did, controller, options) {
throw createVDRError(
"OPERATION_NOT_SUPPORTED" /* OPERATION_NOT_SUPPORTED */,
`updateController not implemented for ${this.method} VDR`,
{ method: this.method, operation: "updateController" }
);
}
/**
* Validates options for update operations and ensures proper permissions
*
* @param did The DID being operated on
* @param document The resolved DID document
* @param keyId The key ID used for signing
* @param requiredRelationship The required verification relationship for this operation
* @throws Error if validation fails
*/
async validateUpdateOperation(did, document, keyId, requiredRelationship) {
this.validateDIDMethod(did);
if (!document) {
throw createDIDError("DID_NOT_FOUND" /* DID_NOT_FOUND */, `DID document ${did} not found`, {
did,
operation: "validateUpdateOperation"
});
}
if (!this.validateKeyPermission(document, keyId, requiredRelationship)) {
throw createValidationError(
"KEY_PERMISSION_DENIED" /* KEY_PERMISSION_DENIED */,
`Key ${keyId} does not have ${requiredRelationship} permission required for this operation`,
{ keyId, requiredRelationship, did }
);
}
return document;
}
/**
* Validates that inputs to addVerificationMethod are correct
*
* @param did The DID being operated on
* @param verificationMethod The verification method to validate
* @param document The current DID document
* @throws Error if validation fails
*/
validateVerificationMethod(did, verificationMethod, document) {
if (!verificationMethod.id.startsWith(did)) {
throw createValidationError(
"VALIDATION_FAILED" /* VALIDATION_FAILED */,
`Verification method ID ${verificationMethod.id} must start with DID ${did}`,
{ verificationMethodId: verificationMethod.id, did }
);
}
if (document.verificationMethod?.some((vm) => vm.id === verificationMethod.id)) {
throw createValidationError(
"VALIDATION_FAILED" /* VALIDATION_FAILED */,
`Verification method ${verificationMethod.id} already exists`,
{ verificationMethodId: verificationMethod.id, did }
);
}
if (!verificationMethod.type) {
throw createValidationError(
"VALIDATION_FAILED" /* VALIDATION_FAILED */,
"Verification method must have a type",
{ verificationMethod, did }
);
}
if (!verificationMethod.controller) {
throw createValidationError(
"VALIDATION_FAILED" /* VALIDATION_FAILED */,
"Verification method must have a controller",
{ verificationMethod, did }
);
}
if (!verificationMethod.publicKeyMultiba