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 @@ -478,6 +478,16 @@ [identityClient], ); } +function useIdentityWalletLogIn(): ( + walletAddress: string, + siweMessage: string, + siweSignature: string, +) => Promise { + const client = React.useContext(IdentityClientContext); + const identityClient = client?.identityClient; + invariant(identityClient, 'Identity client should be set'); + return identityClient.logInWalletUser; +} const logInActionTypes = Object.freeze({ started: 'LOG_IN_STARTED', @@ -772,6 +782,7 @@ logIn as logInRawAction, identityLogInActionTypes, useIdentityPasswordLogIn, + useIdentityWalletLogIn, useLogIn, logInActionTypes, useLogOut, 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 @@ -67,6 +67,11 @@ userID: string, ) => Promise; +generateNonce: () => Promise; + +logInWalletUser: ( + walletAddress: string, + siweMessage: string, + siweSignature: string, + ) => Promise; } export type IdentityServiceAuthLayer = { 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 @@ -264,6 +264,47 @@ identityAuthResultValidator, ); }, + logInWalletUser: async ( + walletAddress: string, + siweMessage: string, + siweSignature: string, + ) => { + await commCoreModule.initializeCryptoAccount(); + const [ + { blobPayload, signature }, + notificationsOneTimeKeys, + primaryOneTimeKeys, + prekeys, + ] = await Promise.all([ + commCoreModule.getUserPublicKey(), + commCoreModule.getNotificationsOneTimeKeys(ONE_TIME_KEYS_NUMBER), // TODO: replace this with new method that only generates keys if needed + commCoreModule.getPrimaryOneTimeKeys(ONE_TIME_KEYS_NUMBER), // TODO: replace this with new method that only generates keys if needed + commCoreModule.validateAndGetPrekeys(), + ]); + const loginResult = await commRustModule.logInWalletUser( + siweMessage, + siweSignature, + blobPayload, + signature, + prekeys.contentPrekey, + prekeys.contentPrekeySignature, + prekeys.notifPrekey, + prekeys.notifPrekeySignature, + getOneTimeKeyValues(primaryOneTimeKeys), + getOneTimeKeyValues(notificationsOneTimeKeys), + ); + const { userID, accessToken: token } = JSON.parse(loginResult); + const identityAuthResult = { + accessToken: token, + userID, + username: walletAddress, + }; + + return assertWithValidator( + identityAuthResult, + identityAuthResultValidator, + ); + }, generateNonce: commRustModule.generateNonce, }), [getAuthMetadata], 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 @@ -28,6 +28,7 @@ OpaqueLoginFinishRequest, OpaqueLoginStartRequest, Prekey, + WalletLoginRequest, } from '../protobufs/identity-unauth-structs.cjs'; import * as IdentityUnauthClient from '../protobufs/identity-unauth.cjs'; @@ -282,6 +283,38 @@ return assertWithValidator(identityAuthResult, identityAuthResultValidator); }; + logInWalletUser: ( + walletAddress: string, + siweMessage: string, + siweSignature: string, + ) => Promise = async ( + walletAddress: string, + siweMessage: string, + siweSignature: string, + ) => { + const identityDeviceKeyUpload = await this.getDeviceKeyUpload(); + const deviceKeyUpload = grpcDeviceKeyUpload(identityDeviceKeyUpload); + + const loginRequest = new WalletLoginRequest(); + loginRequest.setSiweMessage(siweMessage); + loginRequest.setSiweSignature(siweSignature); + loginRequest.setDeviceKeyUpload(deviceKeyUpload); + + let loginResponse; + try { + loginResponse = await this.unauthClient.logInWalletUser(loginRequest); + } catch (e) { + console.log('Error calling logInWalletUser:', e); + throw new Error(getMessageForException(e) ?? 'unknown'); + } + + const userID = loginResponse.getUserId(); + const accessToken = loginResponse.getAccessToken(); + const identityAuthResult = { accessToken, userID, username: walletAddress }; + + return assertWithValidator(identityAuthResult, identityAuthResultValidator); + }; + generateNonce: () => Promise = async () => { const result = await this.unauthClient.generateNonce(new Empty()); return result.getNonce();