diff --git a/ts/components/registration/stages/RestoreAccount.tsx b/ts/components/registration/stages/RestoreAccount.tsx index 083f82fc1..285655b85 100644 --- a/ts/components/registration/stages/RestoreAccount.tsx +++ b/ts/components/registration/stages/RestoreAccount.tsx @@ -18,7 +18,11 @@ import { useProgress, useRecoveryPassword, } from '../../../state/onboarding/selectors/registration'; -import { registerSingleDevice, signInByLinkingDevice } from '../../../util/accountManager'; +import { + registerSingleDevice, + registrationDone, + signInByLinkingDevice, +} from '../../../util/accountManager'; import { setSignInByLinking, setSignWithRecoveryPhrase } from '../../../util/storage'; import { Flex } from '../../basic/Flex'; import { SessionButton, SessionButtonColor } from '../../basic/SessionButton'; @@ -73,20 +77,22 @@ async function signInAndFetchDisplayName( try { await resetRegistration(); - await signInByLinkingDevice(recoveryPassword, 'english', loadingAnimationCallback); + void signInByLinkingDevice(recoveryPassword, 'english', loadingAnimationCallback); - // TODO[epic-899] do we still need this? Should I change the polling timeout to ONBOARDING_RECOVERY_TIMEOUT? - await PromiseUtils.waitForTask(done => { - window.Whisper.events.on('configurationMessageReceived', async (displayName: string) => { - window.log.debug( - `WIP: [signInAndFetchDisplayName] waitForTask done with displayName: "${displayName}"` - ); - window.Whisper.events.off('configurationMessageReceived'); - await setSignInByLinking(false); - await setSignWithRecoveryPhrase(true); - done(displayName); - displayNameFromNetwork = displayName; - }); + await PromiseUtils.waitForTask(() => { + window.Whisper.events.on( + 'configurationMessageReceived', + async (displayName: string, pubkey: string) => { + window.log.debug( + `WIP: [signInAndFetchDisplayName] waitForTask done with displayName: "${displayName}"` + ); + window.Whisper.events.off('configurationMessageReceived'); + await setSignInByLinking(false); + await setSignWithRecoveryPhrase(true); + displayNameFromNetwork = displayName; + await registrationDone(pubkey, displayName); + } + ); }, ONBOARDING_TIMES.RECOVERY_TIMEOUT); if (!displayNameFromNetwork.length) { @@ -100,8 +106,8 @@ async function signInAndFetchDisplayName( window.log.debug( `WIP: [signInAndFetchDisplayName] we got a displayName from network: "${displayNameFromNetwork}"` ); + // Do not set the lastProfileUpdateTimestamp. - // We expect to get a display name from a configuration message while we are loading messages of this user return displayNameFromNetwork; } diff --git a/ts/session/apis/snode_api/swarmPolling.ts b/ts/session/apis/snode_api/swarmPolling.ts index 910235969..e6590ce3b 100644 --- a/ts/session/apis/snode_api/swarmPolling.ts +++ b/ts/session/apis/snode_api/swarmPolling.ts @@ -397,30 +397,38 @@ export class SwarmPolling { ); if (returnAndKeepInMemory) { + let displayName = ''; + try { - const ourKeyPair = await UserUtils.getIdentityKeyPair(); - if (!ourKeyPair) { - throw new Error('ourKeyPair not found'); + const keypair = await UserUtils.getUserED25519KeyPairBytes(); + if (!keypair || !keypair.privKeyBytes) { + throw new Error('edkeypair not found for current user'); } + const privateKeyEd25519 = keypair.privKeyBytes; + // we take the lastest config message to create the wrapper in memory - const configMessage = allDecryptedConfigMessages.at(-1)?.message; - window.log.debug(`WIP: [SwarmPolling] configMessage: ${JSON.stringify(configMessage)}`); - await GenericWrapperActions.init( - 'UserConfig', - new Uint8Array(ourKeyPair.privKey), - configMessage?.data || null - ); + const incomingConfigMessage = allDecryptedConfigMessages.at(-1); window.log.debug( - `WIP: [SwarmPolling] dump: ${StringUtils.toHex(await GenericWrapperActions.dump('UserConfig'))}` + `WIP: [SwarmPolling] configMessage: ${JSON.stringify(incomingConfigMessage)}` ); - // TODO[epic=899] this is still not working + if (!incomingConfigMessage) { + throw new Error('incomingConfigMessage not found'); + } + await GenericWrapperActions.init('UserConfig', privateKeyEd25519, null); + await GenericWrapperActions.merge('UserConfig', [ + { + data: incomingConfigMessage.message.data, + hash: incomingConfigMessage.messageHash, + }, + ]); + const userInfo = await UserConfigWrapperActions.getUserInfo(); window.log.debug(`WIP: [SwarmPolling] userInfo: ${JSON.stringify(userInfo)}`); if (!userInfo) { throw new Error('UserInfo not found'); } - return userInfo.name; + displayName = userInfo.name; } catch (e) { window.log.warn( '[SwarmPolling] LibSessionUtil.initializeLibSessionUtilWrappers failed with', @@ -429,6 +437,8 @@ export class SwarmPolling { } finally { await GenericWrapperActions.free('UserConfig'); } + + return displayName; } await ConfigMessageHandler.handleConfigMessagesViaLibSession(allDecryptedConfigMessages); @@ -650,7 +660,7 @@ export class SwarmPolling { /** * Only exposed as public for testing */ - public async pollOnceForDisplayName(pubkey: PubKey) { + public async pollOnceForDisplayName(pubkey: PubKey): Promise { const polledPubkey = pubkey.key; const swarmSnodes = await snodePool.getSwarmFor(polledPubkey); @@ -704,9 +714,6 @@ export class SwarmPolling { ); try { const displayName = await this.handleSharedConfigMessages(userConfigMessagesMerged, true); - window.log.debug( - `WIP: [pollForOurDisplayName] displayName ${JSON.stringify(displayName)}` - ); return displayName; } catch (e) { window.log.warn( @@ -730,6 +737,7 @@ export class SwarmPolling { try { const displayName = await this.pollOnceForDisplayName(UserUtils.getOurPubKeyFromCache()); + window.log.debug(`WIP: [pollForOurDisplayName] displayName ${displayName}`); return displayName; } catch (e) { window?.log?.warn('pollForOurDisplayName exception: ', e); diff --git a/ts/util/accountManager.ts b/ts/util/accountManager.ts index 7c4bb2484..8018ce2ab 100644 --- a/ts/util/accountManager.ts +++ b/ts/util/accountManager.ts @@ -2,7 +2,7 @@ import { getConversationController } from '../session/conversations'; import { getSodiumRenderer } from '../session/crypto'; import { fromArrayBufferToBase64, fromHex, toHex } from '../session/utils/String'; import { getOurPubKeyStrFromCache } from '../session/utils/User'; -import { trigger } from '../shims/events'; +import { configurationMessageReceived, trigger } from '../shims/events'; import { SettingsKey } from '../data/settings-key'; import { ConversationTypeEnum } from '../models/conversationAttributes'; @@ -79,6 +79,8 @@ export async function signInWithRecovery( * @param mnemonic the mnemonic the user duly saved in a safe place. We will restore his sessionID based on this. * @param mnemonicLanguage 'english' only is supported * @param loadingAnimationCallback a callback to trigger a loading animation + * + * @returns the display name of the user if found on the network */ export async function signInByLinkingDevice( mnemonic: string, @@ -100,9 +102,7 @@ export async function signInByLinkingDevice( const pubKeyString = toHex(identityKeyPair.pubKey); // fetch configuration message to get the user's display name. const displayName = await getSwarmPollingInstance().pollForOurDisplayName(); - - await registrationDone(pubKeyString, displayName); - return pubKeyString; + trigger(configurationMessageReceived, displayName, pubKeyString); } /** * This signs up a new user account. User has no recovery and does not try to link a device @@ -189,7 +189,7 @@ async function createAccount(identityKeyPair: SessionKeyPair) { * @param ourPubkey the pubkey recovered from the seed * @param displayName the display name entered by the user, if any. This is not a display name found from a config message in the network. */ -async function registrationDone(ourPubkey: string, displayName: string) { +export async function registrationDone(ourPubkey: string, displayName: string) { window?.log?.info(`registration done with user provided displayName "${displayName}"`); // initializeLibSessionUtilWrappers needs our publicKey to be set