feat: handle failing to find a display name from the swarm

the user can enter it manually, improved error handling, logging, sync post login
pull/3056/head
William Grant 1 year ago
parent 97cd21a77e
commit c9eac6c83e

@ -1,6 +1,6 @@
import { AnyAction } from '@reduxjs/toolkit'; import { AnyAction } from '@reduxjs/toolkit';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { useEffect } from 'react'; import { useCallback, useEffect } from 'react';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { ONBOARDING_TIMES } from '../../../session/constants'; import { ONBOARDING_TIMES } from '../../../session/constants';
import { trigger } from '../../../shims/events'; import { trigger } from '../../../shims/events';
@ -9,6 +9,7 @@ import {
setAccountRestorationStep, setAccountRestorationStep,
} from '../../../state/onboarding/ducks/registration'; } from '../../../state/onboarding/ducks/registration';
import { registrationDone } from '../../../util/accountManager'; import { registrationDone } from '../../../util/accountManager';
import { setSignWithRecoveryPhrase } from '../../../util/storage';
let interval: NodeJS.Timeout; let interval: NodeJS.Timeout;
@ -33,6 +34,14 @@ export const useRecoveryProgressEffect = (props: UseRecoveryProgressEffectProps)
const dispatch = useDispatch(); const dispatch = useDispatch();
const recoveryComplete = useCallback(async () => {
await setSignWithRecoveryPhrase(true);
await registrationDone(ourPubkey, displayName);
window.log.debug(`WIP: [onboarding] restore account: loggin in for ${displayName}`);
trigger('openInbox');
}, [displayName, ourPubkey]);
useEffect(() => { useEffect(() => {
if (step === AccountRestoration.Loading) { if (step === AccountRestoration.Loading) {
interval = setInterval(() => { interval = setInterval(() => {
@ -44,7 +53,7 @@ export const useRecoveryProgressEffect = (props: UseRecoveryProgressEffectProps)
clearInterval(interval); clearInterval(interval);
// if we didn't get the display name in time, we need to enter it manually // if we didn't get the display name in time, we need to enter it manually
window.log.debug( window.log.debug(
`WIP: [useRecoveryProgressEffect] AccountRestoration.Loading We didn't get the display name in time, so we need to enter it manually` `WIP: [onboarding] restore account: We failed with a time out when fetching a display, so we had to enter it manually`
); );
dispatch(setAccountRestorationStep(AccountRestoration.DisplayName)); dispatch(setAccountRestorationStep(AccountRestoration.DisplayName));
} }
@ -68,15 +77,12 @@ export const useRecoveryProgressEffect = (props: UseRecoveryProgressEffectProps)
interval = setInterval(() => { interval = setInterval(() => {
clearInterval(interval); clearInterval(interval);
if (!isEmpty(displayName)) { if (!isEmpty(displayName)) {
window.log.debug(
`WIP: [useRecoveryProgressEffect] AccountRestoration.Complete Finished progress`
);
dispatch(setAccountRestorationStep(AccountRestoration.Complete)); dispatch(setAccountRestorationStep(AccountRestoration.Complete));
} else { } else {
dispatch(setAccountRestorationStep(AccountRestoration.DisplayName));
window.log.debug( window.log.debug(
`WIP: [onboarding] AccountRestoration.DisplayName failed to fetch display name so we need to enter it manually` `WIP: [onboarding] restore account: We failed with an error when fetching a display name, so we had to enter it manually`
); );
dispatch(setAccountRestorationStep(AccountRestoration.DisplayName));
} }
}, ONBOARDING_TIMES.RECOVERY_FINISHED); }, ONBOARDING_TIMES.RECOVERY_FINISHED);
} }
@ -84,20 +90,15 @@ export const useRecoveryProgressEffect = (props: UseRecoveryProgressEffectProps)
if (step === AccountRestoration.Complete) { if (step === AccountRestoration.Complete) {
clearInterval(interval); clearInterval(interval);
if (!isEmpty(ourPubkey) && !isEmpty(displayName)) { if (!isEmpty(ourPubkey) && !isEmpty(displayName)) {
window.log.debug( void recoveryComplete();
`WIP: [onboarding] AccountRestoration.Complete opening inbox for ${displayName}`
);
// eslint-disable-next-line more/no-then
void registrationDone(ourPubkey, displayName).then(() => trigger('openInbox'));
} else { } else {
window.log.debug( window.log.debug(
`WIP: [onboarding] AccountRestoration.Complete failed to find the pubkey and display name` `WIP: [onboarding] restore account: We don't have a pubkey or display name`
); );
dispatch(setAccountRestorationStep(AccountRestoration.DisplayName)); dispatch(setAccountRestorationStep(AccountRestoration.DisplayName));
} }
} }
return () => clearInterval(interval); return () => clearInterval(interval);
}, [dispatch, displayName, ourPubkey, progress, setProgress, step]); }, [dispatch, displayName, ourPubkey, progress, recoveryComplete, setProgress, step]);
}; };

@ -25,7 +25,7 @@ import {
useRecoveryPasswordError, useRecoveryPasswordError,
} from '../../../state/onboarding/selectors/registration'; } from '../../../state/onboarding/selectors/registration';
import { registerSingleDevice, signInByLinkingDevice } from '../../../util/accountManager'; import { registerSingleDevice, signInByLinkingDevice } from '../../../util/accountManager';
import { setSignInByLinking, setSignWithRecoveryPhrase } from '../../../util/storage'; import { setSignInByLinking } from '../../../util/storage';
import { Flex } from '../../basic/Flex'; import { Flex } from '../../basic/Flex';
import { SessionButton, SessionButtonColor } from '../../basic/SessionButton'; import { SessionButton, SessionButtonColor } from '../../basic/SessionButton';
import { SpacerLG, SpacerSM } from '../../basic/Text'; import { SpacerLG, SpacerSM } from '../../basic/Text';
@ -43,23 +43,26 @@ import { displayNameIsValid, resetRegistration, sanitizeDisplayNameOrToast } fro
* Ask for a display name, as we will drop incoming ConfigurationMessages if any are saved on the swarm. * Ask for a display name, as we will drop incoming ConfigurationMessages if any are saved on the swarm.
* We will handle a ConfigurationMessage * We will handle a ConfigurationMessage
*/ */
async function signInWithNewDisplayName(signInDetails: RecoverDetails) { async function signInWithNewDisplayName(signInDetails: RecoverDetails, dispatch: Dispatch) {
const { displayName, recoveryPassword, errorCallback } = signInDetails; const { displayName, recoveryPassword, errorCallback } = signInDetails;
window.log.debug(`WIP: [signInWithNewDisplayName] starting sign in with new display name....`);
try { try {
const trimName = displayNameIsValid(displayName); const validDisplayName = displayNameIsValid(displayName);
await resetRegistration(); await resetRegistration();
await registerSingleDevice(recoveryPassword, 'english', trimName); await registerSingleDevice(
await setSignInByLinking(false); recoveryPassword,
await setSignWithRecoveryPhrase(true); 'english',
validDisplayName,
async (pubkey: string) => {
dispatch(setHexGeneratedPubKey(pubkey));
dispatch(setDisplayName(validDisplayName));
dispatch(setAccountRestorationStep(AccountRestoration.Finishing));
}
);
} catch (e) { } catch (e) {
await resetRegistration(); await resetRegistration();
errorCallback(e); void errorCallback(e);
window.log.debug(
`WIP: [signInWithNewDisplayName] exception during registration: ${e.message || e}`
);
} }
} }
@ -72,16 +75,19 @@ async function signInAndFetchDisplayName(
/** this is used to trigger the loading animation further down the registration pipeline */ /** this is used to trigger the loading animation further down the registration pipeline */
loadingAnimationCallback: () => void; loadingAnimationCallback: () => void;
}, },
abortSignal: AbortSignal,
dispatch: Dispatch dispatch: Dispatch
) { ) {
const { recoveryPassword, loadingAnimationCallback } = signInDetails; const { recoveryPassword, loadingAnimationCallback } = signInDetails;
try { try {
await resetRegistration(); await resetRegistration();
const promiseLink = signInByLinkingDevice( const promiseLink = signInByLinkingDevice(
recoveryPassword, recoveryPassword,
'english', 'english',
loadingAnimationCallback loadingAnimationCallback,
abortSignal
); );
const promiseWait = PromiseUtils.waitForTask(done => { const promiseWait = PromiseUtils.waitForTask(done => {
@ -90,7 +96,6 @@ async function signInAndFetchDisplayName(
async (ourPubkey: string, displayName: string) => { async (ourPubkey: string, displayName: string) => {
window.Whisper.events.off('configurationMessageReceived'); window.Whisper.events.off('configurationMessageReceived');
await setSignInByLinking(false); await setSignInByLinking(false);
await setSignWithRecoveryPhrase(false);
dispatch(setHexGeneratedPubKey(ourPubkey)); dispatch(setHexGeneratedPubKey(ourPubkey));
dispatch(setDisplayName(displayName)); dispatch(setDisplayName(displayName));
dispatch(setAccountRestorationStep(AccountRestoration.Finishing)); dispatch(setAccountRestorationStep(AccountRestoration.Finishing));
@ -130,6 +135,7 @@ export const RestoreAccount = () => {
return; return;
} }
const abortController = new AbortController();
try { try {
window.log.debug( window.log.debug(
`WIP: [onboarding] restore account: recoverAndFetchDisplayName() is starting recoveryPassword: ${recoveryPassword}` `WIP: [onboarding] restore account: recoverAndFetchDisplayName() is starting recoveryPassword: ${recoveryPassword}`
@ -145,6 +151,7 @@ export const RestoreAccount = () => {
dispatch(setAccountRestorationStep(AccountRestoration.Loading)); dispatch(setAccountRestorationStep(AccountRestoration.Loading));
}, },
}, },
abortController.signal,
dispatch dispatch
); );
} catch (e) { } catch (e) {
@ -153,6 +160,11 @@ export const RestoreAccount = () => {
); );
if (e instanceof NotFoundError || e instanceof TaskTimedOutError) { if (e instanceof NotFoundError || e instanceof TaskTimedOutError) {
if (e instanceof TaskTimedOutError) {
// abort fetching the display name from our swarm
window.log.debug(`WIP: [onboarding] restore account: aborting!`);
abortController.abort();
}
dispatch(setAccountRestorationStep(AccountRestoration.DisplayName)); dispatch(setAccountRestorationStep(AccountRestoration.DisplayName));
return; return;
} }
@ -177,16 +189,17 @@ export const RestoreAccount = () => {
window.log.debug( window.log.debug(
`WIP: [onboarding] restore account: recoverAndEnterDisplayName() is starting recoveryPassword: ${recoveryPassword} displayName: ${displayName}` `WIP: [onboarding] restore account: recoverAndEnterDisplayName() is starting recoveryPassword: ${recoveryPassword} displayName: ${displayName}`
); );
dispatch(setProgress(0)); await signInWithNewDisplayName(
await signInWithNewDisplayName({ {
displayName, displayName,
recoveryPassword, recoveryPassword,
errorCallback: e => { errorCallback: e => {
dispatch(setDisplayNameError(e.message || String(e))); dispatch(setDisplayNameError(e.message || String(e)));
throw e; throw e;
},
}, },
}); dispatch
dispatch(setAccountRestorationStep(AccountRestoration.Complete)); );
} catch (e) { } catch (e) {
window.log.debug( window.log.debug(
`WIP: [onboarding] restore account: restoration with new display name failed! Error: ${e.message || e}` `WIP: [onboarding] restore account: restoration with new display name failed! Error: ${e.message || e}`

@ -659,8 +659,13 @@ export class SwarmPolling {
// return the cached value // return the cached value
return this.lastHashes[nodeEdKey][pubkey][namespace]; return this.lastHashes[nodeEdKey][pubkey][namespace];
} }
public async pollOnceForOurDisplayName(): Promise<string> {
public async pollOnceForOurDisplayName(abortSignal?: AbortSignal): Promise<string> {
try { try {
if (abortSignal?.aborted) {
throw new NotFoundError('[pollOnceForOurDisplayName] aborted right away');
}
const pubkey = UserUtils.getOurPubKeyFromCache(); const pubkey = UserUtils.getOurPubKeyFromCache();
const polledPubkey = pubkey.key; const polledPubkey = pubkey.key;
const swarmSnodes = await snodePool.getSwarmFor(polledPubkey); const swarmSnodes = await snodePool.getSwarmFor(polledPubkey);
@ -675,6 +680,12 @@ export class SwarmPolling {
toPollFrom = sample(notPolled) as Snode; toPollFrom = sample(notPolled) as Snode;
} }
if (abortSignal?.aborted) {
throw new NotFoundError(
'[pollOnceForOurDisplayName] aborted after selecting nodes to poll from'
);
}
const resultsFromUserProfile = await SnodeAPIRetrieve.retrieveDisplayName( const resultsFromUserProfile = await SnodeAPIRetrieve.retrieveDisplayName(
toPollFrom, toPollFrom,
pubkey.key pubkey.key
@ -683,7 +694,13 @@ export class SwarmPolling {
// check if we just fetched the details from the config namespaces. // check if we just fetched the details from the config namespaces.
// If yes, merge them together and exclude them from the rest of the messages. // If yes, merge them together and exclude them from the rest of the messages.
if (!resultsFromUserProfile?.length) { if (!resultsFromUserProfile?.length) {
throw new Error('resultsFromUserProfile is empty'); throw new NotFoundError('resultsFromUserProfile is empty');
}
if (abortSignal?.aborted) {
throw new NotFoundError(
'[pollOnceForOurDisplayName] aborted after retrieving user profile config messages'
);
} }
const userConfigMessages = resultsFromUserProfile const userConfigMessages = resultsFromUserProfile
@ -692,7 +709,7 @@ export class SwarmPolling {
const userConfigMessagesMerged = flatten(compact(userConfigMessages)); const userConfigMessagesMerged = flatten(compact(userConfigMessages));
if (!userConfigMessagesMerged.length) { if (!userConfigMessagesMerged.length) {
throw new Error('after merging there are no user config messages'); throw new NotFoundError('after merging there are no user config messages');
} }
const displayName = await this.handleSharedConfigMessages(userConfigMessagesMerged, true); const displayName = await this.handleSharedConfigMessages(userConfigMessagesMerged, true);
@ -700,7 +717,7 @@ export class SwarmPolling {
throw new NotFoundError('Got a config message from network but without a displayName...'); throw new NotFoundError('Got a config message from network but without a displayName...');
} }
window.log.debug(`WIP: [pollOnceForOurDisplayName] displayName ${displayName}`); // window.log.debug(`[pollOnceForOurDisplayName] displayName found ${displayName}`);
return displayName; return displayName;
} catch (e) { } catch (e) {
if (e.message === ERROR_CODE_NO_CONNECT) { if (e.message === ERROR_CODE_NO_CONNECT) {
@ -710,7 +727,6 @@ export class SwarmPolling {
} else if (!window.inboxStore?.getState().onionPaths.isOnline) { } else if (!window.inboxStore?.getState().onionPaths.isOnline) {
window.inboxStore?.dispatch(updateIsOnline(true)); window.inboxStore?.dispatch(updateIsOnline(true));
} }
window.log.debug(`WIP: [pollOnceForOurDisplayName] no displayName found`, e);
throw e; throw e;
} }
} }

@ -34,29 +34,29 @@ export enum AccountRestoration {
export type OnboardDirection = 'backward' | 'forward'; export type OnboardDirection = 'backward' | 'forward';
export type OnboardingState = { export type OnboardingState = {
step: Onboarding;
direction: OnboardDirection;
accountCreationStep: AccountCreation;
accountRestorationStep: AccountRestoration;
progress: number;
recoveryPassword: string; recoveryPassword: string;
recoveryPasswordError: string | undefined; recoveryPasswordError: string | undefined;
hexGeneratedPubKey: string; hexGeneratedPubKey: string;
displayName: string; displayName: string;
displayNameError: string | undefined; displayNameError: string | undefined;
progress: number;
step: Onboarding;
accountCreationStep: AccountCreation;
accountRestorationStep: AccountRestoration;
direction: OnboardDirection;
}; };
const initialState: OnboardingState = { const initialState: OnboardingState = {
step: Onboarding.Start,
direction: 'forward',
accountCreationStep: AccountCreation.DisplayName,
accountRestorationStep: AccountRestoration.RecoveryPassword,
progress: 0,
recoveryPassword: '', recoveryPassword: '',
recoveryPasswordError: undefined, recoveryPasswordError: undefined,
hexGeneratedPubKey: '', hexGeneratedPubKey: '',
displayName: '', displayName: '',
displayNameError: undefined, displayNameError: undefined,
progress: 0,
step: Onboarding.Start,
accountRestorationStep: AccountRestoration.RecoveryPassword,
accountCreationStep: AccountCreation.DisplayName,
direction: 'forward',
}; };
export const registrationSlice = createSlice({ export const registrationSlice = createSlice({
@ -67,6 +67,21 @@ export const registrationSlice = createSlice({
window.log.debug(`WIP: [onboarding] resetOnboardingState() called`); window.log.debug(`WIP: [onboarding] resetOnboardingState() called`);
return { ...initialState }; return { ...initialState };
}, },
setOnboardingStep(state, action: PayloadAction<Onboarding>) {
return { ...state, step: action.payload };
},
setDirection(state, action: PayloadAction<OnboardDirection>) {
return { ...state, direction: action.payload };
},
setAccountCreationStep(state, action: PayloadAction<AccountCreation>) {
return { ...state, accountCreationStep: action.payload };
},
setAccountRestorationStep(state, action: PayloadAction<AccountRestoration>) {
return { ...state, accountRestorationStep: action.payload };
},
setProgress(state, action: PayloadAction<number>) {
return { ...state, progress: action.payload };
},
setRecoveryPassword(state, action: PayloadAction<string>) { setRecoveryPassword(state, action: PayloadAction<string>) {
return { ...state, recoveryPassword: action.payload }; return { ...state, recoveryPassword: action.payload };
}, },
@ -82,35 +97,20 @@ export const registrationSlice = createSlice({
setDisplayNameError(state, action: PayloadAction<string | undefined>) { setDisplayNameError(state, action: PayloadAction<string | undefined>) {
return { ...state, displayNameError: action.payload }; return { ...state, displayNameError: action.payload };
}, },
setProgress(state, action: PayloadAction<number>) {
return { ...state, progress: action.payload };
},
setOnboardingStep(state, action: PayloadAction<Onboarding>) {
return { ...state, step: action.payload };
},
setAccountCreationStep(state, action: PayloadAction<AccountCreation>) {
return { ...state, accountCreationStep: action.payload };
},
setAccountRestorationStep(state, action: PayloadAction<AccountRestoration>) {
return { ...state, accountRestorationStep: action.payload };
},
setDirection(state, action: PayloadAction<OnboardDirection>) {
return { ...state, direction: action.payload };
},
}, },
}); });
export const { export const {
resetOnboardingState, resetOnboardingState,
setOnboardingStep,
setDirection,
setAccountCreationStep,
setAccountRestorationStep,
setProgress,
setRecoveryPassword, setRecoveryPassword,
setRecoveryPasswordError, setRecoveryPasswordError,
setHexGeneratedPubKey, setHexGeneratedPubKey,
setDisplayName, setDisplayName,
setDisplayNameError, setDisplayNameError,
setProgress,
setOnboardingStep,
setAccountCreationStep,
setAccountRestorationStep,
setDirection,
} = registrationSlice.actions; } = registrationSlice.actions;
export default registrationSlice.reducer; export default registrationSlice.reducer;

@ -14,95 +14,95 @@ const getRegistration = (state: OnboardingStoreState): OnboardingState => {
return state.registration; return state.registration;
}; };
const getRecoveryPassword = createSelector( const getOnboardingStep = createSelector(
getRegistration, getRegistration,
(state: OnboardingState): string => state.recoveryPassword (state: OnboardingState): Onboarding => state.step
); );
const getRecoveryPasswordError = createSelector( const getDirection = createSelector(
getRegistration, getRegistration,
(state: OnboardingState): string | undefined => state.recoveryPasswordError (state: OnboardingState): OnboardDirection => state.direction
); );
const getHexGeneratedPubKey = createSelector( const getAccountCreationStep = createSelector(
getRegistration, getRegistration,
(state: OnboardingState): string => state.hexGeneratedPubKey (state: OnboardingState): AccountCreation => state.accountCreationStep
); );
const getDisplayName = createSelector( const getAccountRestorationStep = createSelector(
getRegistration, getRegistration,
(state: OnboardingState): string => state.displayName (state: OnboardingState): AccountRestoration => state.accountRestorationStep
); );
const getDisplayNameError = createSelector( const getProgress = createSelector(
getRegistration, getRegistration,
(state: OnboardingState): string | undefined => state.displayNameError (state: OnboardingState): number => state.progress
); );
const getProgress = createSelector( const getRecoveryPassword = createSelector(
getRegistration, getRegistration,
(state: OnboardingState): number => state.progress (state: OnboardingState): string => state.recoveryPassword
); );
const getOnboardingStep = createSelector( const getRecoveryPasswordError = createSelector(
getRegistration, getRegistration,
(state: OnboardingState): Onboarding => state.step (state: OnboardingState): string | undefined => state.recoveryPasswordError
); );
const getAccountCreationStep = createSelector( const getHexGeneratedPubKey = createSelector(
getRegistration, getRegistration,
(state: OnboardingState): AccountCreation => state.accountCreationStep (state: OnboardingState): string => state.hexGeneratedPubKey
); );
const getAccountRestorationStep = createSelector( const getDisplayName = createSelector(
getRegistration, getRegistration,
(state: OnboardingState): AccountRestoration => state.accountRestorationStep (state: OnboardingState): string => state.displayName
); );
const getDirection = createSelector( const getDisplayNameError = createSelector(
getRegistration, getRegistration,
(state: OnboardingState): OnboardDirection => state.direction (state: OnboardingState): string | undefined => state.displayNameError
); );
// #endregion // #endregion
// #region Hooks // #region Hooks
export const useRecoveryPassword = () => { export const useOnboardStep = () => {
return useSelector(getRecoveryPassword); return useSelector(getOnboardingStep);
};
export const useRecoveryPasswordError = () => {
return useSelector(getRecoveryPasswordError);
}; };
export const useOnboardHexGeneratedPubKey = () => { export const useOnboardDirection = () => {
return useSelector(getHexGeneratedPubKey); return useSelector(getDirection);
}; };
export const useDisplayName = () => { export const useOnboardAccountCreationStep = () => {
return useSelector(getDisplayName); return useSelector(getAccountCreationStep);
}; };
export const useDisplayNameError = () => { export const useOnboardAccountRestorationStep = () => {
return useSelector(getDisplayNameError); return useSelector(getAccountRestorationStep);
}; };
export const useProgress = () => { export const useProgress = () => {
return useSelector(getProgress); return useSelector(getProgress);
}; };
export const useOnboardStep = () => { export const useRecoveryPassword = () => {
return useSelector(getOnboardingStep); return useSelector(getRecoveryPassword);
}; };
export const useOnboardAccountCreationStep = () => { export const useRecoveryPasswordError = () => {
return useSelector(getAccountCreationStep); return useSelector(getRecoveryPasswordError);
}; };
export const useOnboardAccountRestorationStep = () => { export const useOnboardHexGeneratedPubKey = () => {
return useSelector(getAccountRestorationStep); return useSelector(getHexGeneratedPubKey);
}; };
export const useOnboardDirection = () => { export const useDisplayName = () => {
return useSelector(getDirection); return useSelector(getDisplayName);
};
export const useDisplayNameError = () => {
return useSelector(getDisplayNameError);
}; };
// #endregion // #endregion

@ -67,12 +67,13 @@ const generateKeypair = async (
export async function signInByLinkingDevice( export async function signInByLinkingDevice(
mnemonic: string, mnemonic: string,
mnemonicLanguage: string, mnemonicLanguage: string,
loadingAnimationCallback: () => void loadingAnimationCallback: () => void,
abortSignal: AbortSignal
) { ) {
if (!mnemonic) { if (isEmpty(mnemonic)) {
throw new Error('Session always needs a mnemonic. Either generated or given by the user'); throw new Error('Session always needs a mnemonic. Either generated or given by the user');
} }
if (!mnemonicLanguage) { if (isEmpty(mnemonicLanguage)) {
throw new Error('We always needs a mnemonicLanguage'); throw new Error('We always needs a mnemonicLanguage');
} }
@ -84,7 +85,7 @@ export async function signInByLinkingDevice(
await saveRecoveryPhrase(mnemonic); await saveRecoveryPhrase(mnemonic);
const pubKeyString = toHex(identityKeyPair.pubKey); const pubKeyString = toHex(identityKeyPair.pubKey);
const displayName = await getSwarmPollingInstance().pollOnceForOurDisplayName(); const displayName = await getSwarmPollingInstance().pollOnceForOurDisplayName(abortSignal);
if (isEmpty(pubKeyString)) { if (isEmpty(pubKeyString)) {
throw new Error("We don't have a pubkey from the recovery password..."); throw new Error("We don't have a pubkey from the recovery password...");
@ -106,15 +107,16 @@ export async function signInByLinkingDevice(
export async function registerSingleDevice( export async function registerSingleDevice(
generatedMnemonic: string, generatedMnemonic: string,
mnemonicLanguage: string, mnemonicLanguage: string,
displayName: string displayName: string,
restoreCallback?: (pubkey: string) => Promise<void>
) { ) {
if (!generatedMnemonic) { if (isEmpty(generatedMnemonic)) {
throw new Error('Session always need a mnemonic. Either generated or given by the user'); throw new Error('Session always need a mnemonic. Either generated or given by the user');
} }
if (!mnemonicLanguage) { if (isEmpty(mnemonicLanguage)) {
throw new Error('We always need a mnemonicLanguage'); throw new Error('We always need a mnemonicLanguage');
} }
if (!displayName) { if (isEmpty(displayName)) {
throw new Error('We always need a displayName'); throw new Error('We always need a displayName');
} }
@ -124,7 +126,16 @@ export async function registerSingleDevice(
await saveRecoveryPhrase(generatedMnemonic); await saveRecoveryPhrase(generatedMnemonic);
const pubKeyString = toHex(identityKeyPair.pubKey); const pubKeyString = toHex(identityKeyPair.pubKey);
await registrationDone(pubKeyString, displayName); if (isEmpty(pubKeyString)) {
throw new Error("We don't have a pubkey from the recovery password...");
}
if (restoreCallback) {
// when restoring an account completing the registration is handled by the RestoreAccount component
await restoreCallback(pubKeyString);
} else {
await registrationDone(pubKeyString, displayName);
}
} }
export async function generateMnemonic() { export async function generateMnemonic() {

@ -118,6 +118,8 @@ export async function setSignInByLinking(isLinking: boolean) {
await put('is_sign_in_by_linking', isLinking); await put('is_sign_in_by_linking', isLinking);
} }
/** if we sign in with an existing recovery password, then we don't need to show any of the onboarding ui once we login
*/
export function isSignWithRecoveryPhrase() { export function isSignWithRecoveryPhrase() {
const isRecoveryPhraseUsed = get('is_sign_in_recovery_phrase'); const isRecoveryPhraseUsed = get('is_sign_in_recovery_phrase');
if (isRecoveryPhraseUsed === undefined) { if (isRecoveryPhraseUsed === undefined) {

Loading…
Cancel
Save