A social knowledge tool for researchers built on ATProto
at development 4.0 kB view raw
1import { Result, ok, err } from 'src/shared/core/Result'; 2import { IIdentityResolutionService } from '../../domain/services/IIdentityResolutionService'; 3import { DID } from '../../domain/DID'; 4import { DIDOrHandle } from '../../domain/DIDOrHandle'; 5import { Handle } from '../../domain/Handle'; 6import { IAgentService } from '../../application/IAgentService'; 7 8export class ATProtoIdentityResolutionService 9 implements IIdentityResolutionService 10{ 11 constructor(private readonly agentService: IAgentService) {} 12 13 async resolveToDID(identifier: DIDOrHandle): Promise<Result<DID>> { 14 try { 15 // If it's already a DID, return it directly 16 if (identifier.isDID) { 17 const did = identifier.getDID(); 18 if (!did) { 19 return err(new Error('Invalid DID in identifier')); 20 } 21 return ok(did); 22 } 23 24 // If it's a handle, resolve it to a DID 25 const handle = identifier.getHandle(); 26 if (!handle) { 27 return err(new Error('Invalid handle in identifier')); 28 } 29 30 // Get an unauthenticated agent to resolve the handle 31 const agentResult = this.agentService.getUnauthenticatedAgent(); 32 if (agentResult.isErr()) { 33 return err( 34 new Error( 35 `Failed to get agent for handle resolution: ${agentResult.error.message}`, 36 ), 37 ); 38 } 39 40 const agent = agentResult.value; 41 42 // Resolve the handle to get the DID 43 const profileResult = await agent.resolveHandle({ handle: handle.value }); 44 45 if (!profileResult.success) { 46 return err( 47 new Error( 48 `Failed to resolve handle ${handle.value}: ${JSON.stringify(profileResult)}`, 49 ), 50 ); 51 } 52 53 // Create and return the DID 54 const didResult = DID.create(profileResult.data.did); 55 if (didResult.isErr()) { 56 return err( 57 new Error( 58 `Invalid DID returned from handle resolution: ${didResult.error.message}`, 59 ), 60 ); 61 } 62 63 return ok(didResult.value); 64 } catch (error) { 65 return err( 66 new Error( 67 `Error resolving identifier to DID: ${error instanceof Error ? error.message : String(error)}`, 68 ), 69 ); 70 } 71 } 72 73 async resolveToHandle(identifier: DIDOrHandle): Promise<Result<Handle>> { 74 try { 75 // If it's already a handle, return it directly 76 if (identifier.isHandle) { 77 const handle = identifier.getHandle(); 78 if (!handle) { 79 return err(new Error('Invalid handle in identifier')); 80 } 81 return ok(handle); 82 } 83 84 // If it's a DID, resolve it to a handle 85 const did = identifier.getDID(); 86 if (!did) { 87 return err(new Error('Invalid DID in identifier')); 88 } 89 90 // Get an unauthenticated agent to resolve the DID 91 const agentResult = this.agentService.getUnauthenticatedAgent(); 92 if (agentResult.isErr()) { 93 return err( 94 new Error( 95 `Failed to get agent for DID resolution: ${agentResult.error.message}`, 96 ), 97 ); 98 } 99 100 const agent = agentResult.value; 101 102 // Get the profile to extract the handle 103 const profileResult = await agent.getProfile({ actor: did.value }); 104 105 if (!profileResult.success) { 106 return err( 107 new Error( 108 `Failed to resolve DID ${did.value}: ${JSON.stringify(profileResult)}`, 109 ), 110 ); 111 } 112 113 // Create and return the Handle 114 const handleResult = Handle.create(profileResult.data.handle); 115 if (handleResult.isErr()) { 116 return err( 117 new Error( 118 `Invalid handle returned from DID resolution: ${handleResult.error.message}`, 119 ), 120 ); 121 } 122 123 return ok(handleResult.value); 124 } catch (error) { 125 return err( 126 new Error( 127 `Error resolving identifier to handle: ${error instanceof Error ? error.message : String(error)}`, 128 ), 129 ); 130 } 131 } 132}