/** * @file institutional-identity.ts * @notice Indy identity service for institutional credentials */ export interface DIDDocument { did: string; publicKey: string[]; service: Array<{ id: string; type: string; serviceEndpoint: string; }>; } export interface VerifiableCredential { '@context': string[]; id: string; type: string[]; issuer: string; issuanceDate: string; credentialSubject: { id: string; claims: Record; }; proof: { type: string; created: string; proofPurpose: string; verificationMethod: string; jws: string; }; } export interface IdentityRequest { institutionName: string; institutionType: 'central_bank' | 'commercial_bank' | 'ifi' | 'other'; jurisdiction: string; regulatoryLicense?: string; } export class InstitutionalIdentityService { private indyApiUrl: string; private indyPoolName: string; constructor(indyApiUrl: string, indyPoolName: string = 'dbis-pool') { this.indyApiUrl = indyApiUrl; this.indyPoolName = indyPoolName; } /** * Issue DID for institution */ async issueDID(request: IdentityRequest): Promise { try { const response = await fetch(`${this.indyApiUrl}/api/v1/ledger/did`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ alias: request.institutionName, role: 'TRUSTEE', seed: undefined // In production, use secure seed generation }) }); if (!response.ok) { throw new Error('DID issuance failed'); } const result = await response.json(); return result.didDocument; } catch (error: any) { throw new Error(`DID issuance error: ${error.message}`); } } /** * Issue Verifiable Credential */ async issueCredential( did: string, credentialType: 'KYC' | 'AML' | 'RegulatoryApproval' | 'BankLicense', claims: Record ): Promise { try { const response = await fetch(`${this.indyApiUrl}/api/v1/credentials/issue`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ did, credentialType, claims, schemaId: this.getSchemaId(credentialType) }) }); if (!response.ok) { throw new Error('Credential issuance failed'); } return await response.json(); } catch (error: any) { throw new Error(`Credential issuance error: ${error.message}`); } } /** * Verify credential */ async verifyCredential(credential: VerifiableCredential): Promise<{ valid: boolean; error?: string }> { try { const response = await fetch(`${this.indyApiUrl}/api/v1/credentials/verify`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ credential }) }); if (!response.ok) { return { valid: false, error: 'Verification failed' }; } const result = await response.json(); return { valid: result.valid, error: result.error }; } catch (error: any) { return { valid: false, error: error.message }; } } /** * Get credential for institution */ async getInstitutionCredentials(did: string): Promise { try { const response = await fetch(`${this.indyApiUrl}/api/v1/credentials/${did}`, { method: 'GET', headers: { 'Content-Type': 'application/json' } }); if (!response.ok) { return []; } return await response.json(); } catch (error) { console.error('Get credentials error:', error); return []; } } /** * Check if institution has required credentials for tokenization */ async checkTokenizationEligibility(did: string): Promise<{ eligible: boolean; missingCredentials: string[]; tier: number; }> { const credentials = await this.getInstitutionCredentials(did); const requiredCredentials = ['KYC', 'AML', 'RegulatoryApproval']; const missing: string[] = []; for (const required of requiredCredentials) { const hasCredential = credentials.some( (vc: VerifiableCredential) => vc.type.includes(required) ); if (!hasCredential) { missing.push(required); } } // Determine tier based on credentials let tier = 0; if (credentials.some((vc: VerifiableCredential) => vc.type.includes('BankLicense'))) { tier = 3; // Highest tier } else if (missing.length === 0) { tier = 2; // Full compliance } else if (missing.length === 1) { tier = 1; // Partial compliance } return { eligible: missing.length === 0, missingCredentials: missing, tier }; } /** * Get schema ID for credential type */ private getSchemaId(credentialType: string): string { const schemaMap: Record = { 'KYC': 'KYCSchema:1.0', 'AML': 'AMLSchema:1.0', 'RegulatoryApproval': 'RegulatorySchema:1.0', 'BankLicense': 'BankLicenseSchema:1.0' }; return schemaMap[credentialType] || 'GenericSchema:1.0'; } }