diff --git a/lib/actions/user-actions.js b/lib/actions/user-actions.js --- a/lib/actions/user-actions.js +++ b/lib/actions/user-actions.js @@ -52,7 +52,7 @@ } from '../types/avatar-types.js'; import type { RawEntryInfo, CalendarQuery } from '../types/entry-types.js'; import type { - Identities, + UserIdentitiesResponse, IdentityAuthResult, } from '../types/identity-service-types.js'; import type { @@ -1381,7 +1381,7 @@ function useFindUserIdentities(): ( userIDs: $ReadOnlyArray, -) => Promise { +) => Promise { const client = React.useContext(IdentityClientContext); const identityClient = client?.identityClient; invariant(identityClient, 'Identity client should be set'); diff --git a/lib/components/farcaster-data-handler.react.js b/lib/components/farcaster-data-handler.react.js --- a/lib/components/farcaster-data-handler.react.js +++ b/lib/components/farcaster-data-handler.react.js @@ -124,7 +124,8 @@ const userStoreIDs = Object.keys(userInfos); - const userIdentities = await findUserIdentities(userStoreIDs); + const { identities: userIdentities } = + await findUserIdentities(userStoreIDs); const userStoreFarcasterUsers = Object.entries(userIdentities) .filter(([, identity]) => identity.farcasterID !== null) diff --git a/lib/handlers/user-infos-handler.react.js b/lib/handlers/user-infos-handler.react.js --- a/lib/handlers/user-infos-handler.react.js +++ b/lib/handlers/user-infos-handler.react.js @@ -70,7 +70,7 @@ // 1. Fetch usernames from identity const promise = (async () => { newUserIDs.forEach(id => requestedIDsRef.current.add(id)); - const identities = await findUserIdentities(newUserIDs); + const { identities } = await findUserIdentities(newUserIDs); newUserIDs.forEach(id => requestedIDsRef.current.delete(id)); const newUserInfos = []; 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 @@ -190,7 +190,9 @@ ) => Promise<$ReadOnlyArray>; +linkFarcasterAccount: (farcasterID: string) => Promise; +unlinkFarcasterAccount: () => Promise; - +findUserIdentities: (userIDs: $ReadOnlyArray) => Promise; + +findUserIdentities: ( + userIDs: $ReadOnlyArray, + ) => Promise; +versionSupported: () => Promise; +changePassword: (oldPassword: string, newPassword: string) => Promise; } @@ -282,6 +284,22 @@ identityValidator, ); +export type ReservedUserIdentifiers = { + +[userID: string]: string, +}; +export const reservedIdentifiersValidator: TDict = + t.dict(t.String, t.String); + +export type UserIdentitiesResponse = { + +identities: Identities, + +reservedUserIdentifiers: ReservedUserIdentifiers, +}; +export const userIdentitiesResponseValidator: TInterface = + tShape({ + identities: identitiesValidator, + reservedUserIdentifiers: reservedIdentifiersValidator, + }); + export type SignedDeviceList = { // JSON-stringified RawDeviceList +rawDeviceList: string, diff --git a/native/identity-service/identity-service-context-provider.react.js b/native/identity-service/identity-service-context-provider.react.js --- a/native/identity-service/identity-service-context-provider.react.js +++ b/native/identity-service/identity-service-context-provider.react.js @@ -27,7 +27,7 @@ type UserDevicesOlmInboundKeys, type UserDevicesOlmOutboundKeys, type UsersSignedDeviceLists, - identitiesValidator, + userIdentitiesResponseValidator, type UsersDevicesPlatformDetails, peersDeviceListsValidator, } from 'lib/types/identity-service-types.js'; @@ -666,8 +666,10 @@ token, userIDs, ); - const { identities } = JSON.parse(result); - return assertWithValidator(identities, identitiesValidator); + return assertWithValidator( + JSON.parse(result), + userIdentitiesResponseValidator, + ); }, versionSupported: () => { return commRustModule.versionSupported(); 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 @@ -29,7 +29,8 @@ farcasterUsersValidator, type UsersSignedDeviceLists, type Identities, - identitiesValidator, + type UserIdentitiesResponse, + userIdentitiesResponseValidator, type PeersDeviceLists, peersDeviceListsValidator, type IdentityPlatformDetails, @@ -649,31 +650,41 @@ 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 identityObjects = response.toObject()?.identitiesMap; - - let identities: Identities = {}; - identityObjects.forEach(([userID, identityObject]) => { - identities = { - ...identities, - [userID]: { - ethIdentity: identityObject.ethIdentity, - username: identityObject.username, - farcasterID: identityObject.farcasterId, - }, - }; - }); + 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 responseObject = response.toObject(); + const identityObjects = responseObject?.identitiesMap; + const reservedUserEntries = responseObject?.reservedUserIdentifiersMap; + + let identities: Identities = {}; + identityObjects.forEach(([userID, identityObject]) => { + identities = { + ...identities, + [userID]: { + ethIdentity: identityObject.ethIdentity, + username: identityObject.username, + farcasterID: identityObject.farcasterId, + }, + }; + }); - return assertWithValidator(identities, identitiesValidator); + const userIdentitiesResponse: UserIdentitiesResponse = { + identities, + reservedUserIdentifiers: Object.fromEntries(reservedUserEntries), }; + return assertWithValidator( + userIdentitiesResponse, + userIdentitiesResponseValidator, + ); + }; versionSupported: () => Promise = async () => { const client = this.unauthClient;