diff --git a/lib/types/identity-service-types.js b/lib/types/identity-service-types.js --- a/lib/types/identity-service-types.js +++ b/lib/types/identity-service-types.js @@ -172,6 +172,7 @@ ) => Promise<$ReadOnlyArray>; +linkFarcasterAccount: (farcasterID: string) => Promise; +unlinkFarcasterAccount: () => Promise; + +findUserIdentities: (userIDs: $ReadOnlyArray) => Promise; } export type IdentityServiceAuthLayer = { @@ -230,6 +231,38 @@ +[userID: string]: RawDeviceList, }; +// User Identity types + +export type EthereumIdentityObject = { + walletAddress: string, + siweMessage: string, + siweSignature: string, +}; +export type IdentityObject = { + +username: string, + +walletAddress: ?EthereumIdentityObject, + +farcasterID: ?string, +}; +export type Identities = { + +[userID: string]: IdentityObject, +}; +export const ethereumIdentityObjectValidator: TInterface = + tShape({ + walletAddress: t.String, + siweMessage: t.String, + siweSignature: t.String, + }); +export const identityObjectValidator: TInterface = + tShape({ + username: t.String, + walletAddress: t.maybe(ethereumIdentityObjectValidator), + farcasterID: t.maybe(t.String), + }); +export const identitiesValidator: TDict = t.dict( + t.String, + identityObjectValidator, +); + export type SignedDeviceList = { // JSON-stringified RawDeviceList +rawDeviceList: string, diff --git a/web/grpc/identity-service-client-wrapper.js b/web/grpc/identity-service-client-wrapper.js --- a/web/grpc/identity-service-client-wrapper.js +++ b/web/grpc/identity-service-client-wrapper.js @@ -30,6 +30,8 @@ farcasterUsersValidator, type UsersSignedDeviceLists, usersSignedDeviceListsValidator, + type Identities, + identitiesValidator, } from 'lib/types/identity-service-types.js'; import { getMessageForException } from 'lib/utils/errors.js'; import { assertWithValidator } from 'lib/utils/validation-utils.js'; @@ -615,8 +617,29 @@ } await client.unlinkFarcasterAccount(new Empty()); }; -} + findUserIdentities: (userIDs: $ReadOnlyArray) => Promise = + async userIDs => { + const client = this.authClient; + if (!client) { + throw new Error('Identity service client is not initialized'); + } + const request = new IdentityAuthStructs.UserIdentitiesRequest(); + request.setUserIdsList([...userIDs]); + const response = await client.findUserIdentities(request); + const identitiesMap = response.toObject()?.identitiesMap; + + let identities: Identities = {}; + identitiesMap.forEach(([userID, identityObject]) => { + identities = { + ...identities, + [userID]: identityObject, + }; + }); + + return assertWithValidator(identities, identitiesValidator); + }; +} function authNewDeviceKeyUpload( uploadData: IdentityNewDeviceKeyUpload, ): DeviceKeyUpload { diff --git a/web/grpc/identity-service-context-provider.react.js b/web/grpc/identity-service-context-provider.react.js --- a/web/grpc/identity-service-context-provider.react.js +++ b/web/grpc/identity-service-context-provider.react.js @@ -138,6 +138,7 @@ getFarcasterUsers: proxyMethodToWorker('getFarcasterUsers'), linkFarcasterAccount: proxyMethodToWorker('linkFarcasterAccount'), unlinkFarcasterAccount: proxyMethodToWorker('unlinkFarcasterAccount'), + findUserIdentities: proxyMethodToWorker('findUserIdentities'), }; }, [proxyMethodToWorker]);