@nuwa-ai/identity-kit
Version:
SDK for NIP-1 Agent Single DID Multi-Key Model and NIP-3 CADOP (Custodian-Assisted DID Onboarding Protocol)
721 lines (709 loc) • 26.3 kB
text/typescript
import { SignatureScheme, Keypair } from '@roochnetwork/rooch-sdk';
/**
* Readable enum for supported verification key suites.
*
* NOTE: Replaces the old `KEY_TYPE` const object. Use this in new code to
* improve clarity. Values keep the same long-form strings to avoid breaking
* existing behavior when serialized into DID Documents.
*/
declare enum KeyType {
ED25519 = "Ed25519VerificationKey2020",
SECP256K1 = "EcdsaSecp256k1VerificationKey2019",
ECDSAR1 = "EcdsaSecp256r1VerificationKey2019"
}
/**
* @deprecated Will be removed in the next major version. Use `KeyType` enum instead.
*/
declare const KEY_TYPE: typeof KeyType;
/**
* Type guard to check if a string is a valid KeyType
*/
declare function isKeyType(value: string): value is KeyType;
/**
* Convert a string to KeyType, with runtime validation
* @throws Error if the string is not a valid KeyType
*/
declare function toKeyType(value: string): KeyType;
declare function roochSignatureSchemeToKeyType(scheme: SignatureScheme): KeyType;
declare function keyTypeToRoochSignatureScheme(keyType: KeyType): SignatureScheme;
/**
* https://www.w3.org/TR/webauthn-2/#typedefdef-cosealgorithmidentifier
* Convert a WebAuthn public key algorithm to KeyType, with runtime validation
* @throws Error if the string is not a valid KeyType
*/
declare function algorithmToKeyType(algorithm: number): KeyType | undefined;
/**
* Convert a KeyType to WebAuthn algorithm identifier
*/
declare function keyTypeToAlgorithm(keyType: KeyType): number | undefined;
/**
* Get list of supported WebAuthn algorithms
*/
declare function getSupportedAlgorithms(): number[];
/**
* Type that represents either a KeyType or a string
* Useful for functions that need to accept both strict KeyType and general string values
*/
type KeyTypeInput = KeyType | string;
/**
* Represents the information needed to create a new operational key.
*/
interface OperationalKeyInfo {
idFragment?: string;
type: string;
publicKeyMaterial: Uint8Array | JsonWebKey;
controller?: string;
}
interface VerificationMethod {
id: string;
type: string;
controller: string;
publicKeyMultibase?: string;
publicKeyJwk?: JsonWebKey;
}
interface ServiceEndpoint {
id: string;
type: string;
serviceEndpoint: string;
[key: string]: any;
}
interface DIDDocument {
'@context': string | string[];
id: string;
controller?: string | string[];
verificationMethod?: VerificationMethod[];
authentication?: (string | VerificationMethod)[];
assertionMethod?: (string | VerificationMethod)[];
keyAgreement?: (string | VerificationMethod)[];
capabilityInvocation?: (string | VerificationMethod)[];
capabilityDelegation?: (string | VerificationMethod)[];
service?: ServiceEndpoint[];
[key: string]: any;
}
type VerificationRelationship = 'authentication' | 'assertionMethod' | 'keyAgreement' | 'capabilityInvocation' | 'capabilityDelegation';
/**
* Represents the information needed to add a new service to the DID document.
*/
interface ServiceInfo {
idFragment: string;
type: string;
serviceEndpoint: string;
additionalProperties?: Record<string, any>;
}
/**
* Minimal resolver interface consumed by DIDAuth for DID resolution.
* Any component (VDRRegistry, custom resolver, mock) can implement it.
*/
interface DIDResolver {
resolveDID(did: string, options?: {
forceRefresh?: boolean;
}): Promise<DIDDocument | null>;
}
/**
* Interface for external signers that can be used for master key operations
* This allows the SDK to request signatures from external systems (wallets, HSMs, etc.)
* without directly managing the private keys
*/
interface SignerInterface {
/**
* List all available key IDs that this signer can use
* @returns Promise resolving to an array of key IDs
*/
listKeyIds(): Promise<string[]>;
/**
* Signs data with a specified key
* @param data The data to sign
* @param keyId The ID of the key to use for signing
* @returns A promise that resolves to the signature
*/
signWithKeyId(data: Uint8Array, keyId: string): Promise<Uint8Array>;
/**
* Checks if the signer can sign with a specific key
* @param keyId The ID of the key to check
* @returns A promise that resolves to true if the signer can sign with the key
*/
canSignWithKeyId(keyId: string): Promise<boolean>;
/**
* Get the DID of the signer
* @returns The DID of the signer
*/
getDid(): Promise<string>;
/**
* Get information about a specific key
* @param keyId The ID of the key to get information about
* @returns Key information or undefined if not found
*/
getKeyInfo(keyId: string): Promise<{
type: KeyType;
publicKey: Uint8Array;
} | undefined>;
}
/**
* Type guard utilities for SignerInterface and Signer
* These are more reliable than instanceof when dealing with cross-module dependencies
*/
/**
* Check if an object implements SignerInterface (but not Signer)
* This is more reliable than instanceof when dealing with cross-module dependencies
*/
declare function isSignerInterface(obj: any): obj is SignerInterface;
/**
* DID creation request information
*/
interface DIDCreationRequest {
publicKeyMultibase: string;
keyType?: string;
preferredDID?: string;
controller?: string | string[];
initialRelationships?: VerificationRelationship[];
initialServices?: ServiceEndpoint[];
additionalVerificationMethods?: any[];
customScopes?: string[];
}
/**
* Result of DID creation operation
*/
interface DIDCreationResult {
success: boolean;
didDocument?: DIDDocument;
transactionHash?: string;
blockHeight?: number;
error?: string;
debug?: {
requestedDID?: string;
actualDID?: string;
events?: any[];
transactionResult?: any;
};
}
/**
* CADOP creation request
*/
interface CADOPCreationRequest {
userDidKey: string;
custodianServicePublicKey: string;
custodianServiceVMType: string;
customScopes?: string[];
}
/**
* CADOP controller-based creation request
*/
interface CADOPControllerCreationRequest {
controllerDid: string;
controllerPublicKeyMultibase?: string;
controllerVMType?: string;
custodianServicePublicKey: string;
custodianServiceVMType: string;
customScopes?: string[];
}
/**
* Authentication provider types for CADOP
*/
type AuthProvider = 'webauthn' | 'bitcoin' | 'ethereum';
/**
* Provider constants for CADOP authentication
*/
declare const AUTH_PROVIDERS: {
readonly WEBAUTHN: "webauthn";
readonly BITCOIN: "bitcoin";
readonly ETHEREUM: "ethereum";
};
/**
* Interface for Verifiable Data Registry (VDR) implementations
* A VDR is responsible for storing and retrieving DID Documents
*/
interface VDRInterface {
/**
* Resolve a DID to its DID Document
* @param did The DID to resolve
* @returns Promise resolving to the DID Document or null if not found
*/
resolve(did: string): Promise<DIDDocument | null>;
/**
* Check if a DID exists in the registry
* @param did The DID to check
* @returns Promise resolving to true if the DID exists
*/
exists(did: string): Promise<boolean>;
/**
* Get the DID method supported by this VDR
* @returns The DID method (e.g., 'key', 'web', 'rooch')
*/
getMethod(): string;
/**
* Create a new DID
*
* @param request DID creation request
* @param options Creation options
* @returns DID creation result, containing the actual created DID
*/
create(request: DIDCreationRequest, options?: any): Promise<DIDCreationResult>;
/**
* Create a DID via CADOP
*
* @param request CADOP creation request
* @param options Creation options
* @returns DID creation result
*/
createViaCADOP(request: CADOPCreationRequest, options?: any): Promise<DIDCreationResult>;
/**
* Create a DID via CADOP with controller
*
* @param request CADOP controller creation request
* @param options Creation options
* @returns DID creation result
*/
createViaCADOPWithController(request: CADOPControllerCreationRequest, options?: any): Promise<DIDCreationResult>;
/**
* Add a new verification method to a DID document
*
* @param did The DID to update
* @param verificationMethod The verification method to add
* @param relationships Optional relationships to add the verification method to
* @param options Additional options like signer and keyId
* @returns Promise resolving to true if successful
*/
addVerificationMethod(did: string, verificationMethod: any, relationships?: VerificationRelationship[], options?: any): Promise<boolean>;
/**
* Remove a verification method from a DID document
*
* @param did The DID to update
* @param id The ID of the verification method to remove
* @param options Additional options like signer and keyId
* @returns Promise resolving to true if successful
*/
removeVerificationMethod(did: string, id: string, options?: any): Promise<boolean>;
/**
* Add a service to a DID document
*
* @param did The DID to update
* @param service The service to add
* @param options Additional options like signer and keyId
* @returns Promise resolving to true if successful
*/
addService(did: string, service: ServiceEndpoint, options?: any): Promise<boolean>;
/**
* Remove a service from a DID document
*
* @param did The DID to update
* @param id The ID of the service to remove
* @param options Additional options like signer and keyId
* @returns Promise resolving to true if successful
*/
removeService(did: string, id: string, options?: any): Promise<boolean>;
/**
* Update the verification relationships for a verification method
*
* @param did The DID to update
* @param id The ID of the verification method
* @param add Relationships to add
* @param remove Relationships to remove
* @param options Additional options like signer and keyId
* @returns Promise resolving to true if successful
*/
updateRelationships(did: string, id: string, add: VerificationRelationship[], remove: VerificationRelationship[], options?: any): Promise<boolean>;
/**
* Update the controller of a DID document
*
* @param did The DID to update
* @param controller The new controller value
* @param options Additional options like signer and keyId
* @returns Promise resolving to true if successful
*/
updateController(did: string, controller: string | string[], options?: any): Promise<boolean>;
}
/**
* Represents a stored cryptographic key with its metadata
*/
interface StoredKey {
/** Complete verification method ID (contains the DID + fragment) */
keyId: string;
/** Cryptographic curve/algorithm */
keyType: KeyType;
/** Multibase encoded public key */
publicKeyMultibase: string;
/** Optional multibase encoded private key */
privateKeyMultibase?: string;
/** Generic key-value metadata for implementation-specific extensions */
meta?: Record<string, any>;
}
/**
* Interface for key storage implementations
* Different environments (browser, node, react-native) can provide their own implementations
*/
interface KeyStore {
/**
* List all available key IDs in this store
* @returns Promise resolving to array of key IDs
*/
listKeyIds(): Promise<string[]>;
/**
* Load a key by its ID
* @param keyId Optional key ID to load (if omitted, may return a default key)
* @returns Promise resolving to the stored key or null if not found
*/
load(keyId?: string): Promise<StoredKey | null>;
/**
* Save a key to storage
* @param key The key to save
*/
save(key: StoredKey): Promise<void>;
/**
* Clear a specific key or all keys
* @param keyId Optional key ID to clear (if omitted, clears all keys)
*/
clear(keyId?: string): Promise<void>;
/**
* Optional: Sign data directly using the specified key
* Implementations for WebAuthn or non-extractable CryptoKeys should provide this
* @param keyId ID of the key to use for signing
* @param data Data to sign
* @returns Signature as Uint8Array
*/
sign?(keyId: string, data: Uint8Array): Promise<Uint8Array>;
}
/**
* In-memory implementation of KeyStore
* Useful for testing and SSR environments
*/
declare class MemoryKeyStore implements KeyStore {
private map;
/**
* List all available key IDs in this store
*/
listKeyIds(): Promise<string[]>;
/**
* Load a key by its ID
* @param keyId Key ID to load
*/
load(keyId?: string): Promise<StoredKey | null>;
/**
* Save a key to in-memory storage
* @param key The key to save
*/
save(key: StoredKey): Promise<void>;
/**
* Clear a specific key or all keys
* @param keyId Optional key ID to clear (if omitted, clears all keys)
*/
clear(keyId?: string): Promise<void>;
}
interface DIDDocumentCache {
/**
* Retrieve a cached DID Document, if present.
* Returns undefined if the DID has not been cached, or null if the DID was previously
* resolved and not found (negative-cache).
*/
get(did: string): DIDDocument | null | undefined;
/**
* Store the resolution result for a DID. Allows negative-caching by passing null.
*/
set(did: string, doc: DIDDocument | null): void;
/**
* Check whether a DID is present in the cache (either as a DID Document or as a negative entry).
*/
has(did: string): boolean;
/**
* Delete a single DID from the cache.
*/
delete(did: string): void;
/**
* Clear all cached entries.
*/
clear(): void;
}
/**
* Global registry for VDR (Verifiable Data Registry) implementations.
* This singleton manages all registered VDRs and maintains a DID Document cache.
*/
declare class VDRRegistry implements DIDResolver {
private static instance;
private vdrs;
private cache;
private constructor();
static getInstance(): VDRRegistry;
/** Register a VDR implementation for its DID method (e.g., 'key', 'rooch'). */
registerVDR(vdr: VDRInterface): void;
/** Retrieve a previously registered VDR implementation by its method. */
getVDR(method: string): VDRInterface | undefined;
/**
* Override the default cache implementation.
* This allows developers to provide their own cache (e.g., Redis, browser storage).
*/
setCache(cache: DIDDocumentCache): void;
/** Returns the currently configured cache instance. */
getCache(): DIDDocumentCache;
resolveDID(did: string, options?: {
forceRefresh?: boolean;
}): Promise<DIDDocument | null>;
createDID(method: string, creationRequest: DIDCreationRequest, options?: Record<string, any>): Promise<DIDCreationResult>;
createDIDViaCADOP(method: string, creationRequest: CADOPCreationRequest, options?: Record<string, any>): Promise<DIDCreationResult>;
createDIDViaCADOPWithController(method: string, creationRequest: CADOPControllerCreationRequest, options?: Record<string, any>): Promise<DIDCreationResult>;
exists(did: string): Promise<boolean>;
}
/**
* Options for initializing a KeyManager
*/
interface KeyManagerOptions {
/** The key store to use (defaults to MemoryKeyStore) */
store?: KeyStore;
/** Default key type to use when generating keys (defaults to Ed25519) */
defaultKeyType?: KeyType;
/** DID to associate with keys */
did?: string;
}
/**
* KeyManager provides unified key lifecycle management
* It implements SignerInterface and delegates to an underlying KeyStoreSigner
*/
declare class KeyManager implements SignerInterface {
private store;
private defaultKeyType;
private did?;
/**
* Create a new KeyManager
* @param options Configuration options
*/
constructor(options?: KeyManagerOptions);
/**
* Generate a new key and store it
* @param fragment Optional fragment for the key ID (e.g., 'key-1')
* @param keyType Optional key type (defaults to the manager's defaultKeyType)
* @returns The stored key information
*/
generateKey(fragment?: string, keyType?: KeyType): Promise<StoredKey>;
/**
* Import an existing key into the store
* @param key The key to import
*/
importKey(key: StoredKey): Promise<void>;
/**
* Delete a key from the store
* @param keyId ID of the key to delete
*/
deleteKey(keyId: string): Promise<void>;
/**
* Clear all keys from the store
*/
clear(): Promise<void>;
/**
* List all available key IDs
*/
listKeyIds(): Promise<string[]>;
/**
* Get a stored key by its ID
* @param keyId ID of the key to retrieve
* @returns The stored key or null if not found
*/
getStoredKey(keyId: string): Promise<StoredKey | null>;
/**
* Set the DID for this manager
* @param did The DID to set
*/
setDid(did: string): void;
/**
* Get the DID
* @returns The DID
*/
getDid(): Promise<string>;
/**
* Sign data with a specific key
* @param data Data to sign
* @param keyId ID of the key to use
* @returns The signature
*/
signWithKeyId(data: Uint8Array, keyId: string): Promise<Uint8Array>;
/**
* Check if a key is available for signing
* @param keyId ID of the key to check
* @returns True if the key exists and can be used for signing
*/
canSignWithKeyId(keyId: string): Promise<boolean>;
/**
* Get information about a specific key
* @param keyId ID of the key to get information about
* @returns Key information or undefined if not found
*/
getKeyInfo(keyId: string): Promise<{
type: KeyType;
publicKey: Uint8Array;
} | undefined>;
/**
* Find the first key with a specific key type
* @param keyType The key type to search for
* @returns The key ID or undefined if not found
*/
findKeyByType(keyType: KeyType): Promise<string | undefined>;
/**
* Get the underlying key store
* @returns The key store
*/
getStore(): KeyStore;
/** Create an empty KeyManager instance and bind DID */
static createEmpty(did: string, store?: KeyStore): KeyManager;
/** Create KeyManager and immediately generate a key */
static createWithNewKey(did: string, fragment?: string, type?: KeyType, store?: KeyStore): Promise<{
keyManager: KeyManager;
keyId: string;
}>;
/** Create KeyManager and import existing key pair */
static createWithKeyPair(did: string, keyPair: {
privateKey: Uint8Array;
publicKey: Uint8Array;
}, fragment?: string, type?: KeyType, store?: KeyStore): Promise<{
keyManager: KeyManager;
keyId: string;
}>;
/** Utility: generate did:key + master key */
static createWithDidKey(): Promise<{
keyManager: KeyManager;
keyId: string;
did: string;
}>;
/** Instance helper: import raw key pair (Uint8Array) */
importKeyPair(fragment: string, keyPair: {
privateKey: Uint8Array;
publicKey: Uint8Array;
}, type?: KeyType): Promise<string>;
/** Instance helper: import Rooch Keypair */
importRoochKeyPair(fragment: string, roochKeyPair: Keypair): Promise<string>;
/**
* Export a stored key to a base58btc encoded string
* @param keyId The ID of the key to export
* @returns base58btc encoded string representation of the StoredKey
*/
exportKeyToString(keyId: string): Promise<string>;
/**
* Import a StoredKey from a base58btc encoded string into the current KeyManager
* @param serialized The base58btc encoded string representation of a StoredKey
* @returns The imported StoredKey
*/
importKeyFromString(serialized: string): Promise<StoredKey>;
/**
* Create a new KeyManager from a serialized StoredKey string
* @param serialized The base58btc encoded string representation of a StoredKey
* @param store Optional key store (defaults to MemoryKeyStore)
* @returns A new KeyManager instance with the imported key
*/
static fromSerializedKey(serialized: string, store?: KeyStore): Promise<KeyManager>;
}
/**
* IdentityEnv – runtime environment prepared by the Builder/bootstrap.
* It wires together VDRRegistry + KeyManager, but **does not** automatically create a DID.
*/
declare class IdentityEnv {
registry: VDRRegistry;
keyManager: KeyManager;
constructor(registry: VDRRegistry, keyManager: KeyManager);
/**
* Load an existing DID and return a ready IdentityKit instance
*/
loadDid(did: string, signer?: SignerInterface): Promise<IdentityKit>;
/**
* Load from a known DID Document
*/
fromDocument(doc: DIDDocument, signer?: SignerInterface): Promise<IdentityKit>;
/**
* Create a new DID via the underlying VDR
*/
createDid(method: string, request: DIDCreationRequest, signer?: SignerInterface, options?: Record<string, any>): Promise<IdentityKit>;
}
/**
* Builder for configuring IdentityEnv step-by-step
*/
declare class IdentityEnvBuilder {
private vdrConfigs;
private keyStore?;
private keyManager?;
/** Register (or ensure) a VDR for given DID method */
useVDR(method: string, options?: any): this;
/** Provide a custom KeyStore implementation */
useKeyStore(store: KeyStore): this;
/** Provide a pre-built KeyManager (advanced) */
useKeyManager(manager: KeyManager): this;
/** Finalise and return the environment */
init(): Promise<IdentityEnv>;
}
/** Convenience helper similar to the old `init()` but **without** auto-creating DID */
declare function bootstrapIdentityEnv(opts?: {
method?: string;
keyStore?: KeyStore;
vdrOptions?: any;
}): Promise<IdentityEnv>;
/**
* Main SDK class for implementing NIP-1 Agent Single DID Multi-Key Model
*/
declare class IdentityKit {
private didDocument;
private vdr;
private signer;
private constructor();
/**
* Create an instance from an existing DID (for managing existing DIDs)
*/
static fromExistingDID(did: string, signer: SignerInterface): Promise<IdentityKit>;
/**
* Create an instance from a DID Document (for scenarios with known DID Document)
*/
static fromDIDDocument(didDocument: DIDDocument, signer: SignerInterface): IdentityKit;
/**
* Create and publish a new DID
*/
static createNewDID(method: string, creationRequest: DIDCreationRequest, signer: SignerInterface, options?: Record<string, any>): Promise<IdentityKit>;
/**
* Lightweight environment bootstrap – prepares VDR(s) & KeyManager without touching DID.
* It is a thin wrapper around `bootstrapIdentityEnv()` so that callers can simply do:
* ```ts
* const env = await IdentityKit.bootstrap({ method: 'rooch' });
* const kit = await env.loadDid(did);
* ```
*/
static bootstrap(opts?: {
method?: string;
keyStore?: KeyStore;
vdrOptions?: any;
}): Promise<IdentityEnv>;
/**
* Find a key that has the specified verification relationship and is available for signing
* @param relationship The required verification relationship
* @returns The key ID if found, undefined otherwise
*/
private findKeyWithRelationship;
/**
* Find all keys that have the specified verification relationship and are available for signing
* @param relationship The required verification relationship
* @returns Array of key IDs that match the criteria
*/
private findKeysWithRelationship;
addVerificationMethod(keyInfo: OperationalKeyInfo, relationships: VerificationRelationship[], options?: {
keyId?: string;
scopes?: string[];
}): Promise<string>;
removeVerificationMethod(keyId: string, options?: {
keyId?: string;
}): Promise<boolean>;
updateVerificationMethodRelationships(keyId: string, addRelationships: VerificationRelationship[], removeRelationships: VerificationRelationship[], options: {
signer?: SignerInterface;
}): Promise<boolean>;
addService(serviceInfo: ServiceInfo, options?: {
keyId?: string;
}): Promise<string>;
removeService(serviceId: string, options?: {
keyId?: string;
}): Promise<boolean>;
getDIDDocument(): DIDDocument;
findServiceByType(serviceType: string): ServiceEndpoint | undefined;
findVerificationMethodsByRelationship(relationship: VerificationRelationship): VerificationMethod[];
canSignWithKey(keyId: string): Promise<boolean>;
private updateLocalDIDDocument;
getSigner(): SignerInterface;
/**
* Get all key IDs that are both present in DID document and available via Signer,
* grouped by verification relationship.
*/
getAvailableKeyIds(): Promise<{
[key in VerificationRelationship]?: string[];
}>;
private static readonly logger;
}
export { AUTH_PROVIDERS as A, IdentityEnvBuilder as B, type CADOPCreationRequest as C, type DIDDocumentCache as D, bootstrapIdentityEnv as E, IdentityKit as I, KeyType as K, MemoryKeyStore as M, type OperationalKeyInfo as O, type SignerInterface as S, type VerificationRelationship as V, type KeyStore as a, type DIDDocument as b, type VerificationMethod as c, type ServiceEndpoint as d, type DIDCreationRequest as e, type DIDCreationResult as f, type CADOPControllerCreationRequest as g, VDRRegistry as h, type VDRInterface as i, type ServiceInfo as j, type KeyTypeInput as k, type DIDResolver as l, type StoredKey as m, KEY_TYPE as n, isKeyType as o, keyTypeToRoochSignatureScheme as p, algorithmToKeyType as q, roochSignatureSchemeToKeyType as r, keyTypeToAlgorithm as s, toKeyType as t, getSupportedAlgorithms as u, type AuthProvider as v, type KeyManagerOptions as w, KeyManager as x, isSignerInterface as y, IdentityEnv as z };